2013-11-29 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob4f211975581e39b1c0c1e96f7b25e1b56df68e0c
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2013 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "stringpool.h"
28 #include "gfortran.h"
29 #include "flags.h"
30 #include "trans.h"
31 #include "trans-stmt.h"
32 #include "trans-types.h"
33 #include "trans-array.h"
34 #include "trans-const.h"
35 #include "arith.h"
36 #include "dependency.h"
37 #include "ggc.h"
39 typedef struct iter_info
41 tree var;
42 tree start;
43 tree end;
44 tree step;
45 struct iter_info *next;
47 iter_info;
49 typedef struct forall_info
51 iter_info *this_loop;
52 tree mask;
53 tree maskindex;
54 int nvar;
55 tree size;
56 struct forall_info *prev_nest;
57 bool do_concurrent;
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
113 || code->label1->defined == ST_LABEL_DO_TARGET)
115 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
116 len_tree = integer_minus_one_node;
118 else
120 gfc_expr *format = code->label1->format;
122 label_len = format->value.character.length;
123 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
124 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
125 format->value.character.string);
126 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
129 gfc_add_modify (&se.pre, len, len_tree);
130 gfc_add_modify (&se.pre, addr, label_tree);
132 return gfc_finish_block (&se.pre);
135 /* Translate a GOTO statement. */
137 tree
138 gfc_trans_goto (gfc_code * code)
140 locus loc = code->loc;
141 tree assigned_goto;
142 tree target;
143 tree tmp;
144 gfc_se se;
146 if (code->label1 != NULL)
147 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
149 /* ASSIGNED GOTO. */
150 gfc_init_se (&se, NULL);
151 gfc_start_block (&se.pre);
152 gfc_conv_label_variable (&se, code->expr1);
153 tmp = GFC_DECL_STRING_LEN (se.expr);
154 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
155 build_int_cst (TREE_TYPE (tmp), -1));
156 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
157 "Assigned label is not a target label");
159 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
161 /* We're going to ignore a label list. It does not really change the
162 statement's semantics (because it is just a further restriction on
163 what's legal code); before, we were comparing label addresses here, but
164 that's a very fragile business and may break with optimization. So
165 just ignore it. */
167 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
168 assigned_goto);
169 gfc_add_expr_to_block (&se.pre, target);
170 return gfc_finish_block (&se.pre);
174 /* Translate an ENTRY statement. Just adds a label for this entry point. */
175 tree
176 gfc_trans_entry (gfc_code * code)
178 return build1_v (LABEL_EXPR, code->ext.entry->label);
182 /* Replace a gfc_ss structure by another both in the gfc_se struct
183 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
184 to replace a variable ss by the corresponding temporary. */
186 static void
187 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
189 gfc_ss **sess, **loopss;
191 /* The old_ss is a ss for a single variable. */
192 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
194 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
195 if (*sess == old_ss)
196 break;
197 gcc_assert (*sess != gfc_ss_terminator);
199 *sess = new_ss;
200 new_ss->next = old_ss->next;
203 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
204 loopss = &((*loopss)->loop_chain))
205 if (*loopss == old_ss)
206 break;
207 gcc_assert (*loopss != gfc_ss_terminator);
209 *loopss = new_ss;
210 new_ss->loop_chain = old_ss->loop_chain;
211 new_ss->loop = old_ss->loop;
213 gfc_free_ss (old_ss);
217 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
218 elemental subroutines. Make temporaries for output arguments if any such
219 dependencies are found. Output arguments are chosen because internal_unpack
220 can be used, as is, to copy the result back to the variable. */
221 static void
222 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
223 gfc_symbol * sym, gfc_actual_arglist * arg,
224 gfc_dep_check check_variable)
226 gfc_actual_arglist *arg0;
227 gfc_expr *e;
228 gfc_formal_arglist *formal;
229 gfc_se parmse;
230 gfc_ss *ss;
231 gfc_symbol *fsym;
232 tree data;
233 tree size;
234 tree tmp;
236 if (loopse->ss == NULL)
237 return;
239 ss = loopse->ss;
240 arg0 = arg;
241 formal = gfc_sym_get_dummy_args (sym);
243 /* Loop over all the arguments testing for dependencies. */
244 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
246 e = arg->expr;
247 if (e == NULL)
248 continue;
250 /* Obtain the info structure for the current argument. */
251 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
252 if (ss->info->expr == e)
253 break;
255 /* If there is a dependency, create a temporary and use it
256 instead of the variable. */
257 fsym = formal ? formal->sym : NULL;
258 if (e->expr_type == EXPR_VARIABLE
259 && e->rank && fsym
260 && fsym->attr.intent != INTENT_IN
261 && gfc_check_fncall_dependency (e, fsym->attr.intent,
262 sym, arg0, check_variable))
264 tree initial, temptype;
265 stmtblock_t temp_post;
266 gfc_ss *tmp_ss;
268 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
269 GFC_SS_SECTION);
270 gfc_mark_ss_chain_used (tmp_ss, 1);
271 tmp_ss->info->expr = ss->info->expr;
272 replace_ss (loopse, ss, tmp_ss);
274 /* Obtain the argument descriptor for unpacking. */
275 gfc_init_se (&parmse, NULL);
276 parmse.want_pointer = 1;
277 gfc_conv_expr_descriptor (&parmse, e);
278 gfc_add_block_to_block (&se->pre, &parmse.pre);
280 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
281 initialize the array temporary with a copy of the values. */
282 if (fsym->attr.intent == INTENT_INOUT
283 || (fsym->ts.type ==BT_DERIVED
284 && fsym->attr.intent == INTENT_OUT))
285 initial = parmse.expr;
286 /* For class expressions, we always initialize with the copy of
287 the values. */
288 else if (e->ts.type == BT_CLASS)
289 initial = parmse.expr;
290 else
291 initial = NULL_TREE;
293 if (e->ts.type != BT_CLASS)
295 /* Find the type of the temporary to create; we don't use the type
296 of e itself as this breaks for subcomponent-references in e
297 (where the type of e is that of the final reference, but
298 parmse.expr's type corresponds to the full derived-type). */
299 /* TODO: Fix this somehow so we don't need a temporary of the whole
300 array but instead only the components referenced. */
301 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
302 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
303 temptype = TREE_TYPE (temptype);
304 temptype = gfc_get_element_type (temptype);
307 else
308 /* For class arrays signal that the size of the dynamic type has to
309 be obtained from the vtable, using the 'initial' expression. */
310 temptype = NULL_TREE;
312 /* Generate the temporary. Cleaning up the temporary should be the
313 very last thing done, so we add the code to a new block and add it
314 to se->post as last instructions. */
315 size = gfc_create_var (gfc_array_index_type, NULL);
316 data = gfc_create_var (pvoid_type_node, NULL);
317 gfc_init_block (&temp_post);
318 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
319 temptype, initial, false, true,
320 false, &arg->expr->where);
321 gfc_add_modify (&se->pre, size, tmp);
322 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
323 gfc_add_modify (&se->pre, data, tmp);
325 /* Update other ss' delta. */
326 gfc_set_delta (loopse->loop);
328 /* Copy the result back using unpack..... */
329 if (e->ts.type != BT_CLASS)
330 tmp = build_call_expr_loc (input_location,
331 gfor_fndecl_in_unpack, 2, parmse.expr, data);
332 else
334 /* ... except for class results where the copy is
335 unconditional. */
336 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
337 tmp = gfc_conv_descriptor_data_get (tmp);
338 tmp = build_call_expr_loc (input_location,
339 builtin_decl_explicit (BUILT_IN_MEMCPY),
340 3, tmp, data,
341 fold_convert (size_type_node, size));
343 gfc_add_expr_to_block (&se->post, tmp);
345 /* parmse.pre is already added above. */
346 gfc_add_block_to_block (&se->post, &parmse.post);
347 gfc_add_block_to_block (&se->post, &temp_post);
353 /* Get the interface symbol for the procedure corresponding to the given call.
354 We can't get the procedure symbol directly as we have to handle the case
355 of (deferred) type-bound procedures. */
357 static gfc_symbol *
358 get_proc_ifc_for_call (gfc_code *c)
360 gfc_symbol *sym;
362 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
364 sym = gfc_get_proc_ifc_for_expr (c->expr1);
366 /* Fall back/last resort try. */
367 if (sym == NULL)
368 sym = c->resolved_sym;
370 return sym;
374 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
376 tree
377 gfc_trans_call (gfc_code * code, bool dependency_check,
378 tree mask, tree count1, bool invert)
380 gfc_se se;
381 gfc_ss * ss;
382 int has_alternate_specifier;
383 gfc_dep_check check_variable;
384 tree index = NULL_TREE;
385 tree maskexpr = NULL_TREE;
386 tree tmp;
388 /* A CALL starts a new block because the actual arguments may have to
389 be evaluated first. */
390 gfc_init_se (&se, NULL);
391 gfc_start_block (&se.pre);
393 gcc_assert (code->resolved_sym);
395 ss = gfc_ss_terminator;
396 if (code->resolved_sym->attr.elemental)
397 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
398 get_proc_ifc_for_call (code),
399 GFC_SS_REFERENCE);
401 /* Is not an elemental subroutine call with array valued arguments. */
402 if (ss == gfc_ss_terminator)
405 /* Translate the call. */
406 has_alternate_specifier
407 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
408 code->expr1, NULL);
410 /* A subroutine without side-effect, by definition, does nothing! */
411 TREE_SIDE_EFFECTS (se.expr) = 1;
413 /* Chain the pieces together and return the block. */
414 if (has_alternate_specifier)
416 gfc_code *select_code;
417 gfc_symbol *sym;
418 select_code = code->next;
419 gcc_assert(select_code->op == EXEC_SELECT);
420 sym = select_code->expr1->symtree->n.sym;
421 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
422 if (sym->backend_decl == NULL)
423 sym->backend_decl = gfc_get_symbol_decl (sym);
424 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
426 else
427 gfc_add_expr_to_block (&se.pre, se.expr);
429 gfc_add_block_to_block (&se.pre, &se.post);
432 else
434 /* An elemental subroutine call with array valued arguments has
435 to be scalarized. */
436 gfc_loopinfo loop;
437 stmtblock_t body;
438 stmtblock_t block;
439 gfc_se loopse;
440 gfc_se depse;
442 /* gfc_walk_elemental_function_args renders the ss chain in the
443 reverse order to the actual argument order. */
444 ss = gfc_reverse_ss (ss);
446 /* Initialize the loop. */
447 gfc_init_se (&loopse, NULL);
448 gfc_init_loopinfo (&loop);
449 gfc_add_ss_to_loop (&loop, ss);
451 gfc_conv_ss_startstride (&loop);
452 /* TODO: gfc_conv_loop_setup generates a temporary for vector
453 subscripts. This could be prevented in the elemental case
454 as temporaries are handled separatedly
455 (below in gfc_conv_elemental_dependencies). */
456 gfc_conv_loop_setup (&loop, &code->expr1->where);
457 gfc_mark_ss_chain_used (ss, 1);
459 /* Convert the arguments, checking for dependencies. */
460 gfc_copy_loopinfo_to_se (&loopse, &loop);
461 loopse.ss = ss;
463 /* For operator assignment, do dependency checking. */
464 if (dependency_check)
465 check_variable = ELEM_CHECK_VARIABLE;
466 else
467 check_variable = ELEM_DONT_CHECK_VARIABLE;
469 gfc_init_se (&depse, NULL);
470 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
471 code->ext.actual, check_variable);
473 gfc_add_block_to_block (&loop.pre, &depse.pre);
474 gfc_add_block_to_block (&loop.post, &depse.post);
476 /* Generate the loop body. */
477 gfc_start_scalarized_body (&loop, &body);
478 gfc_init_block (&block);
480 if (mask && count1)
482 /* Form the mask expression according to the mask. */
483 index = count1;
484 maskexpr = gfc_build_array_ref (mask, index, NULL);
485 if (invert)
486 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
487 TREE_TYPE (maskexpr), maskexpr);
490 /* Add the subroutine call to the block. */
491 gfc_conv_procedure_call (&loopse, code->resolved_sym,
492 code->ext.actual, code->expr1,
493 NULL);
495 if (mask && count1)
497 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
498 build_empty_stmt (input_location));
499 gfc_add_expr_to_block (&loopse.pre, tmp);
500 tmp = fold_build2_loc (input_location, PLUS_EXPR,
501 gfc_array_index_type,
502 count1, gfc_index_one_node);
503 gfc_add_modify (&loopse.pre, count1, tmp);
505 else
506 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
508 gfc_add_block_to_block (&block, &loopse.pre);
509 gfc_add_block_to_block (&block, &loopse.post);
511 /* Finish up the loop block and the loop. */
512 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
513 gfc_trans_scalarizing_loops (&loop, &body);
514 gfc_add_block_to_block (&se.pre, &loop.pre);
515 gfc_add_block_to_block (&se.pre, &loop.post);
516 gfc_add_block_to_block (&se.pre, &se.post);
517 gfc_cleanup_loop (&loop);
520 return gfc_finish_block (&se.pre);
524 /* Translate the RETURN statement. */
526 tree
527 gfc_trans_return (gfc_code * code)
529 if (code->expr1)
531 gfc_se se;
532 tree tmp;
533 tree result;
535 /* If code->expr is not NULL, this return statement must appear
536 in a subroutine and current_fake_result_decl has already
537 been generated. */
539 result = gfc_get_fake_result_decl (NULL, 0);
540 if (!result)
542 gfc_warning ("An alternate return at %L without a * dummy argument",
543 &code->expr1->where);
544 return gfc_generate_return ();
547 /* Start a new block for this statement. */
548 gfc_init_se (&se, NULL);
549 gfc_start_block (&se.pre);
551 gfc_conv_expr (&se, code->expr1);
553 /* Note that the actually returned expression is a simple value and
554 does not depend on any pointers or such; thus we can clean-up with
555 se.post before returning. */
556 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
557 result, fold_convert (TREE_TYPE (result),
558 se.expr));
559 gfc_add_expr_to_block (&se.pre, tmp);
560 gfc_add_block_to_block (&se.pre, &se.post);
562 tmp = gfc_generate_return ();
563 gfc_add_expr_to_block (&se.pre, tmp);
564 return gfc_finish_block (&se.pre);
567 return gfc_generate_return ();
571 /* Translate the PAUSE statement. We have to translate this statement
572 to a runtime library call. */
574 tree
575 gfc_trans_pause (gfc_code * code)
577 tree gfc_int4_type_node = gfc_get_int_type (4);
578 gfc_se se;
579 tree tmp;
581 /* Start a new block for this statement. */
582 gfc_init_se (&se, NULL);
583 gfc_start_block (&se.pre);
586 if (code->expr1 == NULL)
588 tmp = build_int_cst (gfc_int4_type_node, 0);
589 tmp = build_call_expr_loc (input_location,
590 gfor_fndecl_pause_string, 2,
591 build_int_cst (pchar_type_node, 0), tmp);
593 else if (code->expr1->ts.type == BT_INTEGER)
595 gfc_conv_expr (&se, code->expr1);
596 tmp = build_call_expr_loc (input_location,
597 gfor_fndecl_pause_numeric, 1,
598 fold_convert (gfc_int4_type_node, se.expr));
600 else
602 gfc_conv_expr_reference (&se, code->expr1);
603 tmp = build_call_expr_loc (input_location,
604 gfor_fndecl_pause_string, 2,
605 se.expr, se.string_length);
608 gfc_add_expr_to_block (&se.pre, tmp);
610 gfc_add_block_to_block (&se.pre, &se.post);
612 return gfc_finish_block (&se.pre);
616 /* Translate the STOP statement. We have to translate this statement
617 to a runtime library call. */
619 tree
620 gfc_trans_stop (gfc_code *code, bool error_stop)
622 tree gfc_int4_type_node = gfc_get_int_type (4);
623 gfc_se se;
624 tree tmp;
626 /* Start a new block for this statement. */
627 gfc_init_se (&se, NULL);
628 gfc_start_block (&se.pre);
630 if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
632 /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
633 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
634 tmp = build_call_expr_loc (input_location, tmp, 0);
635 gfc_add_expr_to_block (&se.pre, tmp);
637 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_finalize, 0);
638 gfc_add_expr_to_block (&se.pre, tmp);
641 if (code->expr1 == NULL)
643 tmp = build_int_cst (gfc_int4_type_node, 0);
644 tmp = build_call_expr_loc (input_location,
645 error_stop
646 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
647 ? gfor_fndecl_caf_error_stop_str
648 : gfor_fndecl_error_stop_string)
649 : gfor_fndecl_stop_string,
650 2, build_int_cst (pchar_type_node, 0), tmp);
652 else if (code->expr1->ts.type == BT_INTEGER)
654 gfc_conv_expr (&se, code->expr1);
655 tmp = build_call_expr_loc (input_location,
656 error_stop
657 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
658 ? gfor_fndecl_caf_error_stop
659 : gfor_fndecl_error_stop_numeric)
660 : gfor_fndecl_stop_numeric_f08, 1,
661 fold_convert (gfc_int4_type_node, se.expr));
663 else
665 gfc_conv_expr_reference (&se, code->expr1);
666 tmp = build_call_expr_loc (input_location,
667 error_stop
668 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
669 ? gfor_fndecl_caf_error_stop_str
670 : gfor_fndecl_error_stop_string)
671 : gfor_fndecl_stop_string,
672 2, se.expr, se.string_length);
675 gfc_add_expr_to_block (&se.pre, tmp);
677 gfc_add_block_to_block (&se.pre, &se.post);
679 return gfc_finish_block (&se.pre);
683 tree
684 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
686 gfc_se se, argse;
687 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
689 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
690 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
691 if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
692 return NULL_TREE;
694 gfc_init_se (&se, NULL);
695 gfc_start_block (&se.pre);
697 if (code->expr2)
699 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
700 gfc_init_se (&argse, NULL);
701 gfc_conv_expr_val (&argse, code->expr2);
702 stat = argse.expr;
705 if (code->expr4)
707 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
708 gfc_init_se (&argse, NULL);
709 gfc_conv_expr_val (&argse, code->expr4);
710 lock_acquired = argse.expr;
713 if (stat != NULL_TREE)
714 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
716 if (lock_acquired != NULL_TREE)
717 gfc_add_modify (&se.pre, lock_acquired,
718 fold_convert (TREE_TYPE (lock_acquired),
719 boolean_true_node));
721 return gfc_finish_block (&se.pre);
725 tree
726 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
728 gfc_se se, argse;
729 tree tmp;
730 tree images = NULL_TREE, stat = NULL_TREE,
731 errmsg = NULL_TREE, errmsglen = NULL_TREE;
733 /* Short cut: For single images without bound checking or without STAT=,
734 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
735 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
736 && gfc_option.coarray != GFC_FCOARRAY_LIB)
737 return NULL_TREE;
739 gfc_init_se (&se, NULL);
740 gfc_start_block (&se.pre);
742 if (code->expr1 && code->expr1->rank == 0)
744 gfc_init_se (&argse, NULL);
745 gfc_conv_expr_val (&argse, code->expr1);
746 images = argse.expr;
749 if (code->expr2)
751 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
752 gfc_init_se (&argse, NULL);
753 gfc_conv_expr_val (&argse, code->expr2);
754 stat = argse.expr;
756 else
757 stat = null_pointer_node;
759 if (code->expr3 && gfc_option.coarray == GFC_FCOARRAY_LIB
760 && type != EXEC_SYNC_MEMORY)
762 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
763 gfc_init_se (&argse, NULL);
764 gfc_conv_expr (&argse, code->expr3);
765 gfc_conv_string_parameter (&argse);
766 errmsg = gfc_build_addr_expr (NULL, argse.expr);
767 errmsglen = argse.string_length;
769 else if (gfc_option.coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY)
771 errmsg = null_pointer_node;
772 errmsglen = build_int_cst (integer_type_node, 0);
775 /* Check SYNC IMAGES(imageset) for valid image index.
776 FIXME: Add a check for image-set arrays. */
777 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
778 && code->expr1->rank == 0)
780 tree cond;
781 if (gfc_option.coarray != GFC_FCOARRAY_LIB)
782 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
783 images, build_int_cst (TREE_TYPE (images), 1));
784 else
786 tree cond2;
787 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
788 images, gfort_gvar_caf_num_images);
789 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
790 images,
791 build_int_cst (TREE_TYPE (images), 1));
792 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
793 boolean_type_node, cond, cond2);
795 gfc_trans_runtime_check (true, false, cond, &se.pre,
796 &code->expr1->where, "Invalid image number "
797 "%d in SYNC IMAGES",
798 fold_convert (integer_type_node, images));
801 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
802 image control statements SYNC IMAGES and SYNC ALL. */
803 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
805 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
806 tmp = build_call_expr_loc (input_location, tmp, 0);
807 gfc_add_expr_to_block (&se.pre, tmp);
810 if (gfc_option.coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
812 /* Set STAT to zero. */
813 if (code->expr2)
814 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
816 else if (type == EXEC_SYNC_ALL)
818 /* SYNC ALL => stat == null_pointer_node
819 SYNC ALL(stat=s) => stat has an integer type
821 If "stat" has the wrong integer type, use a temp variable of
822 the right type and later cast the result back into "stat". */
823 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
825 if (TREE_TYPE (stat) == integer_type_node)
826 stat = gfc_build_addr_expr (NULL, stat);
828 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
829 3, stat, errmsg, errmsglen);
830 gfc_add_expr_to_block (&se.pre, tmp);
832 else
834 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
836 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
837 3, gfc_build_addr_expr (NULL, tmp_stat),
838 errmsg, errmsglen);
839 gfc_add_expr_to_block (&se.pre, tmp);
841 gfc_add_modify (&se.pre, stat,
842 fold_convert (TREE_TYPE (stat), tmp_stat));
845 else
847 tree len;
849 gcc_assert (type == EXEC_SYNC_IMAGES);
851 if (!code->expr1)
853 len = build_int_cst (integer_type_node, -1);
854 images = null_pointer_node;
856 else if (code->expr1->rank == 0)
858 len = build_int_cst (integer_type_node, 1);
859 images = gfc_build_addr_expr (NULL_TREE, images);
861 else
863 /* FIXME. */
864 if (code->expr1->ts.kind != gfc_c_int_kind)
865 gfc_fatal_error ("Sorry, only support for integer kind %d "
866 "implemented for image-set at %L",
867 gfc_c_int_kind, &code->expr1->where);
869 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
870 images = se.expr;
872 tmp = gfc_typenode_for_spec (&code->expr1->ts);
873 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
874 tmp = gfc_get_element_type (tmp);
876 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
877 TREE_TYPE (len), len,
878 fold_convert (TREE_TYPE (len),
879 TYPE_SIZE_UNIT (tmp)));
880 len = fold_convert (integer_type_node, len);
883 /* SYNC IMAGES(imgs) => stat == null_pointer_node
884 SYNC IMAGES(imgs,stat=s) => stat has an integer type
886 If "stat" has the wrong integer type, use a temp variable of
887 the right type and later cast the result back into "stat". */
888 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
890 if (TREE_TYPE (stat) == integer_type_node)
891 stat = gfc_build_addr_expr (NULL, stat);
893 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
894 5, fold_convert (integer_type_node, len),
895 images, stat, errmsg, errmsglen);
896 gfc_add_expr_to_block (&se.pre, tmp);
898 else
900 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
902 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
903 5, fold_convert (integer_type_node, len),
904 images, gfc_build_addr_expr (NULL, tmp_stat),
905 errmsg, errmsglen);
906 gfc_add_expr_to_block (&se.pre, tmp);
908 gfc_add_modify (&se.pre, stat,
909 fold_convert (TREE_TYPE (stat), tmp_stat));
913 return gfc_finish_block (&se.pre);
917 /* Generate GENERIC for the IF construct. This function also deals with
918 the simple IF statement, because the front end translates the IF
919 statement into an IF construct.
921 We translate:
923 IF (cond) THEN
924 then_clause
925 ELSEIF (cond2)
926 elseif_clause
927 ELSE
928 else_clause
929 ENDIF
931 into:
933 pre_cond_s;
934 if (cond_s)
936 then_clause;
938 else
940 pre_cond_s
941 if (cond_s)
943 elseif_clause
945 else
947 else_clause;
951 where COND_S is the simplified version of the predicate. PRE_COND_S
952 are the pre side-effects produced by the translation of the
953 conditional.
954 We need to build the chain recursively otherwise we run into
955 problems with folding incomplete statements. */
957 static tree
958 gfc_trans_if_1 (gfc_code * code)
960 gfc_se if_se;
961 tree stmt, elsestmt;
962 locus saved_loc;
963 location_t loc;
965 /* Check for an unconditional ELSE clause. */
966 if (!code->expr1)
967 return gfc_trans_code (code->next);
969 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
970 gfc_init_se (&if_se, NULL);
971 gfc_start_block (&if_se.pre);
973 /* Calculate the IF condition expression. */
974 if (code->expr1->where.lb)
976 gfc_save_backend_locus (&saved_loc);
977 gfc_set_backend_locus (&code->expr1->where);
980 gfc_conv_expr_val (&if_se, code->expr1);
982 if (code->expr1->where.lb)
983 gfc_restore_backend_locus (&saved_loc);
985 /* Translate the THEN clause. */
986 stmt = gfc_trans_code (code->next);
988 /* Translate the ELSE clause. */
989 if (code->block)
990 elsestmt = gfc_trans_if_1 (code->block);
991 else
992 elsestmt = build_empty_stmt (input_location);
994 /* Build the condition expression and add it to the condition block. */
995 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
996 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
997 elsestmt);
999 gfc_add_expr_to_block (&if_se.pre, stmt);
1001 /* Finish off this statement. */
1002 return gfc_finish_block (&if_se.pre);
1005 tree
1006 gfc_trans_if (gfc_code * code)
1008 stmtblock_t body;
1009 tree exit_label;
1011 /* Create exit label so it is available for trans'ing the body code. */
1012 exit_label = gfc_build_label_decl (NULL_TREE);
1013 code->exit_label = exit_label;
1015 /* Translate the actual code in code->block. */
1016 gfc_init_block (&body);
1017 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1019 /* Add exit label. */
1020 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1022 return gfc_finish_block (&body);
1026 /* Translate an arithmetic IF expression.
1028 IF (cond) label1, label2, label3 translates to
1030 if (cond <= 0)
1032 if (cond < 0)
1033 goto label1;
1034 else // cond == 0
1035 goto label2;
1037 else // cond > 0
1038 goto label3;
1040 An optimized version can be generated in case of equal labels.
1041 E.g., if label1 is equal to label2, we can translate it to
1043 if (cond <= 0)
1044 goto label1;
1045 else
1046 goto label3;
1049 tree
1050 gfc_trans_arithmetic_if (gfc_code * code)
1052 gfc_se se;
1053 tree tmp;
1054 tree branch1;
1055 tree branch2;
1056 tree zero;
1058 /* Start a new block. */
1059 gfc_init_se (&se, NULL);
1060 gfc_start_block (&se.pre);
1062 /* Pre-evaluate COND. */
1063 gfc_conv_expr_val (&se, code->expr1);
1064 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1066 /* Build something to compare with. */
1067 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1069 if (code->label1->value != code->label2->value)
1071 /* If (cond < 0) take branch1 else take branch2.
1072 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1073 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1074 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1076 if (code->label1->value != code->label3->value)
1077 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1078 se.expr, zero);
1079 else
1080 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1081 se.expr, zero);
1083 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1084 tmp, branch1, branch2);
1086 else
1087 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1089 if (code->label1->value != code->label3->value
1090 && code->label2->value != code->label3->value)
1092 /* if (cond <= 0) take branch1 else take branch2. */
1093 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1094 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1095 se.expr, zero);
1096 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1097 tmp, branch1, branch2);
1100 /* Append the COND_EXPR to the evaluation of COND, and return. */
1101 gfc_add_expr_to_block (&se.pre, branch1);
1102 return gfc_finish_block (&se.pre);
1106 /* Translate a CRITICAL block. */
1107 tree
1108 gfc_trans_critical (gfc_code *code)
1110 stmtblock_t block;
1111 tree tmp;
1113 gfc_start_block (&block);
1115 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1117 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_critical, 0);
1118 gfc_add_expr_to_block (&block, tmp);
1121 tmp = gfc_trans_code (code->block->next);
1122 gfc_add_expr_to_block (&block, tmp);
1124 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1126 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_critical,
1128 gfc_add_expr_to_block (&block, tmp);
1132 return gfc_finish_block (&block);
1136 /* Do proper initialization for ASSOCIATE names. */
1138 static void
1139 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1141 gfc_expr *e;
1142 tree tmp;
1143 bool class_target;
1144 bool unlimited;
1145 tree desc;
1146 tree offset;
1147 tree dim;
1148 int n;
1150 gcc_assert (sym->assoc);
1151 e = sym->assoc->target;
1153 class_target = (e->expr_type == EXPR_VARIABLE)
1154 && (gfc_is_class_scalar_expr (e)
1155 || gfc_is_class_array_ref (e, NULL));
1157 unlimited = UNLIMITED_POLY (e);
1159 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1160 to array temporary) for arrays with either unknown shape or if associating
1161 to a variable. */
1162 if (sym->attr.dimension && !class_target
1163 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1165 gfc_se se;
1166 tree desc;
1168 desc = sym->backend_decl;
1170 /* If association is to an expression, evaluate it and create temporary.
1171 Otherwise, get descriptor of target for pointer assignment. */
1172 gfc_init_se (&se, NULL);
1173 if (sym->assoc->variable)
1175 se.direct_byref = 1;
1176 se.expr = desc;
1178 gfc_conv_expr_descriptor (&se, e);
1180 /* If we didn't already do the pointer assignment, set associate-name
1181 descriptor to the one generated for the temporary. */
1182 if (!sym->assoc->variable)
1184 int dim;
1186 gfc_add_modify (&se.pre, desc, se.expr);
1188 /* The generated descriptor has lower bound zero (as array
1189 temporary), shift bounds so we get lower bounds of 1. */
1190 for (dim = 0; dim < e->rank; ++dim)
1191 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1192 dim, gfc_index_one_node);
1195 /* Done, register stuff as init / cleanup code. */
1196 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1197 gfc_finish_block (&se.post));
1200 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1201 arrays to be assigned directly. */
1202 else if (class_target && sym->attr.dimension
1203 && (sym->ts.type == BT_DERIVED || unlimited))
1205 gfc_se se;
1207 gfc_init_se (&se, NULL);
1208 se.descriptor_only = 1;
1209 gfc_conv_expr (&se, e);
1211 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1212 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1214 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1216 if (unlimited)
1218 /* Recover the dtype, which has been overwritten by the
1219 assignment from an unlimited polymorphic object. */
1220 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1221 gfc_add_modify (&se.pre, tmp,
1222 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1225 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1226 gfc_finish_block (&se.post));
1229 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1230 else if (gfc_is_associate_pointer (sym))
1232 gfc_se se;
1234 gcc_assert (!sym->attr.dimension);
1236 gfc_init_se (&se, NULL);
1238 /* Class associate-names come this way because they are
1239 unconditionally associate pointers and the symbol is scalar. */
1240 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1242 /* For a class array we need a descriptor for the selector. */
1243 gfc_conv_expr_descriptor (&se, e);
1245 /* Obtain a temporary class container for the result. */
1246 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1247 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1249 /* Set the offset. */
1250 desc = gfc_class_data_get (se.expr);
1251 offset = gfc_index_zero_node;
1252 for (n = 0; n < e->rank; n++)
1254 dim = gfc_rank_cst[n];
1255 tmp = fold_build2_loc (input_location, MULT_EXPR,
1256 gfc_array_index_type,
1257 gfc_conv_descriptor_stride_get (desc, dim),
1258 gfc_conv_descriptor_lbound_get (desc, dim));
1259 offset = fold_build2_loc (input_location, MINUS_EXPR,
1260 gfc_array_index_type,
1261 offset, tmp);
1263 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1265 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1266 && CLASS_DATA (e)->attr.dimension)
1268 /* This is bound to be a class array element. */
1269 gfc_conv_expr_reference (&se, e);
1270 /* Get the _vptr component of the class object. */
1271 tmp = gfc_get_vptr_from_expr (se.expr);
1272 /* Obtain a temporary class container for the result. */
1273 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1274 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1276 else
1277 gfc_conv_expr (&se, e);
1279 tmp = TREE_TYPE (sym->backend_decl);
1280 tmp = gfc_build_addr_expr (tmp, se.expr);
1281 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1283 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1284 gfc_finish_block (&se.post));
1287 /* Do a simple assignment. This is for scalar expressions, where we
1288 can simply use expression assignment. */
1289 else
1291 gfc_expr *lhs;
1293 lhs = gfc_lval_expr_from_sym (sym);
1294 tmp = gfc_trans_assignment (lhs, e, false, true);
1295 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1298 /* Set the stringlength from the vtable size. */
1299 if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
1301 tree charlen;
1302 gfc_se se;
1303 gfc_init_se (&se, NULL);
1304 gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
1305 tmp = gfc_get_symbol_decl (e->symtree->n.sym);
1306 tmp = gfc_vtable_size_get (tmp);
1307 gfc_get_symbol_decl (sym);
1308 charlen = sym->ts.u.cl->backend_decl;
1309 gfc_add_modify (&se.pre, charlen,
1310 fold_convert (TREE_TYPE (charlen), tmp));
1311 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1312 gfc_finish_block (&se.post));
1317 /* Translate a BLOCK construct. This is basically what we would do for a
1318 procedure body. */
1320 tree
1321 gfc_trans_block_construct (gfc_code* code)
1323 gfc_namespace* ns;
1324 gfc_symbol* sym;
1325 gfc_wrapped_block block;
1326 tree exit_label;
1327 stmtblock_t body;
1328 gfc_association_list *ass;
1330 ns = code->ext.block.ns;
1331 gcc_assert (ns);
1332 sym = ns->proc_name;
1333 gcc_assert (sym);
1335 /* Process local variables. */
1336 gcc_assert (!sym->tlink);
1337 sym->tlink = sym;
1338 gfc_process_block_locals (ns);
1340 /* Generate code including exit-label. */
1341 gfc_init_block (&body);
1342 exit_label = gfc_build_label_decl (NULL_TREE);
1343 code->exit_label = exit_label;
1344 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1345 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1347 /* Finish everything. */
1348 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1349 gfc_trans_deferred_vars (sym, &block);
1350 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1351 trans_associate_var (ass->st->n.sym, &block);
1353 return gfc_finish_wrapped_block (&block);
1357 /* Translate the simple DO construct. This is where the loop variable has
1358 integer type and step +-1. We can't use this in the general case
1359 because integer overflow and floating point errors could give incorrect
1360 results.
1361 We translate a do loop from:
1363 DO dovar = from, to, step
1364 body
1365 END DO
1369 [Evaluate loop bounds and step]
1370 dovar = from;
1371 if ((step > 0) ? (dovar <= to) : (dovar => to))
1373 for (;;)
1375 body;
1376 cycle_label:
1377 cond = (dovar == to);
1378 dovar += step;
1379 if (cond) goto end_label;
1382 end_label:
1384 This helps the optimizers by avoiding the extra induction variable
1385 used in the general case. */
1387 static tree
1388 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1389 tree from, tree to, tree step, tree exit_cond)
1391 stmtblock_t body;
1392 tree type;
1393 tree cond;
1394 tree tmp;
1395 tree saved_dovar = NULL;
1396 tree cycle_label;
1397 tree exit_label;
1398 location_t loc;
1400 type = TREE_TYPE (dovar);
1402 loc = code->ext.iterator->start->where.lb->location;
1404 /* Initialize the DO variable: dovar = from. */
1405 gfc_add_modify_loc (loc, pblock, dovar,
1406 fold_convert (TREE_TYPE(dovar), from));
1408 /* Save value for do-tinkering checking. */
1409 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1411 saved_dovar = gfc_create_var (type, ".saved_dovar");
1412 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1415 /* Cycle and exit statements are implemented with gotos. */
1416 cycle_label = gfc_build_label_decl (NULL_TREE);
1417 exit_label = gfc_build_label_decl (NULL_TREE);
1419 /* Put the labels where they can be found later. See gfc_trans_do(). */
1420 code->cycle_label = cycle_label;
1421 code->exit_label = exit_label;
1423 /* Loop body. */
1424 gfc_start_block (&body);
1426 /* Main loop body. */
1427 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1428 gfc_add_expr_to_block (&body, tmp);
1430 /* Label for cycle statements (if needed). */
1431 if (TREE_USED (cycle_label))
1433 tmp = build1_v (LABEL_EXPR, cycle_label);
1434 gfc_add_expr_to_block (&body, tmp);
1437 /* Check whether someone has modified the loop variable. */
1438 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1440 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1441 dovar, saved_dovar);
1442 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1443 "Loop variable has been modified");
1446 /* Exit the loop if there is an I/O result condition or error. */
1447 if (exit_cond)
1449 tmp = build1_v (GOTO_EXPR, exit_label);
1450 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1451 exit_cond, tmp,
1452 build_empty_stmt (loc));
1453 gfc_add_expr_to_block (&body, tmp);
1456 /* Evaluate the loop condition. */
1457 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1458 to);
1459 cond = gfc_evaluate_now_loc (loc, cond, &body);
1461 /* Increment the loop variable. */
1462 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1463 gfc_add_modify_loc (loc, &body, dovar, tmp);
1465 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1466 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1468 /* The loop exit. */
1469 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1470 TREE_USED (exit_label) = 1;
1471 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1472 cond, tmp, build_empty_stmt (loc));
1473 gfc_add_expr_to_block (&body, tmp);
1475 /* Finish the loop body. */
1476 tmp = gfc_finish_block (&body);
1477 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1479 /* Only execute the loop if the number of iterations is positive. */
1480 if (tree_int_cst_sgn (step) > 0)
1481 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1482 to);
1483 else
1484 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1485 to);
1486 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1487 build_empty_stmt (loc));
1488 gfc_add_expr_to_block (pblock, tmp);
1490 /* Add the exit label. */
1491 tmp = build1_v (LABEL_EXPR, exit_label);
1492 gfc_add_expr_to_block (pblock, tmp);
1494 return gfc_finish_block (pblock);
1497 /* Translate the DO construct. This obviously is one of the most
1498 important ones to get right with any compiler, but especially
1499 so for Fortran.
1501 We special case some loop forms as described in gfc_trans_simple_do.
1502 For other cases we implement them with a separate loop count,
1503 as described in the standard.
1505 We translate a do loop from:
1507 DO dovar = from, to, step
1508 body
1509 END DO
1513 [evaluate loop bounds and step]
1514 empty = (step > 0 ? to < from : to > from);
1515 countm1 = (to - from) / step;
1516 dovar = from;
1517 if (empty) goto exit_label;
1518 for (;;)
1520 body;
1521 cycle_label:
1522 dovar += step
1523 countm1t = countm1;
1524 countm1--;
1525 if (countm1t == 0) goto exit_label;
1527 exit_label:
1529 countm1 is an unsigned integer. It is equal to the loop count minus one,
1530 because the loop count itself can overflow. */
1532 tree
1533 gfc_trans_do (gfc_code * code, tree exit_cond)
1535 gfc_se se;
1536 tree dovar;
1537 tree saved_dovar = NULL;
1538 tree from;
1539 tree to;
1540 tree step;
1541 tree countm1;
1542 tree type;
1543 tree utype;
1544 tree cond;
1545 tree cycle_label;
1546 tree exit_label;
1547 tree tmp;
1548 stmtblock_t block;
1549 stmtblock_t body;
1550 location_t loc;
1552 gfc_start_block (&block);
1554 loc = code->ext.iterator->start->where.lb->location;
1556 /* Evaluate all the expressions in the iterator. */
1557 gfc_init_se (&se, NULL);
1558 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1559 gfc_add_block_to_block (&block, &se.pre);
1560 dovar = se.expr;
1561 type = TREE_TYPE (dovar);
1563 gfc_init_se (&se, NULL);
1564 gfc_conv_expr_val (&se, code->ext.iterator->start);
1565 gfc_add_block_to_block (&block, &se.pre);
1566 from = gfc_evaluate_now (se.expr, &block);
1568 gfc_init_se (&se, NULL);
1569 gfc_conv_expr_val (&se, code->ext.iterator->end);
1570 gfc_add_block_to_block (&block, &se.pre);
1571 to = gfc_evaluate_now (se.expr, &block);
1573 gfc_init_se (&se, NULL);
1574 gfc_conv_expr_val (&se, code->ext.iterator->step);
1575 gfc_add_block_to_block (&block, &se.pre);
1576 step = gfc_evaluate_now (se.expr, &block);
1578 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1580 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1581 build_zero_cst (type));
1582 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1583 "DO step value is zero");
1586 /* Special case simple loops. */
1587 if (TREE_CODE (type) == INTEGER_TYPE
1588 && (integer_onep (step)
1589 || tree_int_cst_equal (step, integer_minus_one_node)))
1590 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1593 if (TREE_CODE (type) == INTEGER_TYPE)
1594 utype = unsigned_type_for (type);
1595 else
1596 utype = unsigned_type_for (gfc_array_index_type);
1597 countm1 = gfc_create_var (utype, "countm1");
1599 /* Cycle and exit statements are implemented with gotos. */
1600 cycle_label = gfc_build_label_decl (NULL_TREE);
1601 exit_label = gfc_build_label_decl (NULL_TREE);
1602 TREE_USED (exit_label) = 1;
1604 /* Put these labels where they can be found later. */
1605 code->cycle_label = cycle_label;
1606 code->exit_label = exit_label;
1608 /* Initialize the DO variable: dovar = from. */
1609 gfc_add_modify (&block, dovar, from);
1611 /* Save value for do-tinkering checking. */
1612 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1614 saved_dovar = gfc_create_var (type, ".saved_dovar");
1615 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1618 /* Initialize loop count and jump to exit label if the loop is empty.
1619 This code is executed before we enter the loop body. We generate:
1620 if (step > 0)
1622 if (to < from)
1623 goto exit_label;
1624 countm1 = (to - from) / step;
1626 else
1628 if (to > from)
1629 goto exit_label;
1630 countm1 = (from - to) / -step;
1634 if (TREE_CODE (type) == INTEGER_TYPE)
1636 tree pos, neg, tou, fromu, stepu, tmp2;
1638 /* The distance from FROM to TO cannot always be represented in a signed
1639 type, thus use unsigned arithmetic, also to avoid any undefined
1640 overflow issues. */
1641 tou = fold_convert (utype, to);
1642 fromu = fold_convert (utype, from);
1643 stepu = fold_convert (utype, step);
1645 /* For a positive step, when to < from, exit, otherwise compute
1646 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
1647 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1648 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1649 fold_build2_loc (loc, MINUS_EXPR, utype,
1650 tou, fromu),
1651 stepu);
1652 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1653 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1654 exit_label),
1655 fold_build2 (MODIFY_EXPR, void_type_node,
1656 countm1, tmp2));
1658 /* For a negative step, when to > from, exit, otherwise compute
1659 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1660 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1661 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1662 fold_build2_loc (loc, MINUS_EXPR, utype,
1663 fromu, tou),
1664 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
1665 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1666 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1667 exit_label),
1668 fold_build2 (MODIFY_EXPR, void_type_node,
1669 countm1, tmp2));
1671 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1672 build_int_cst (TREE_TYPE (step), 0));
1673 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
1675 gfc_add_expr_to_block (&block, tmp);
1677 else
1679 tree pos_step;
1681 /* TODO: We could use the same width as the real type.
1682 This would probably cause more problems that it solves
1683 when we implement "long double" types. */
1685 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1686 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1687 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1688 gfc_add_modify (&block, countm1, tmp);
1690 /* We need a special check for empty loops:
1691 empty = (step > 0 ? to < from : to > from); */
1692 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1693 build_zero_cst (type));
1694 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1695 fold_build2_loc (loc, LT_EXPR,
1696 boolean_type_node, to, from),
1697 fold_build2_loc (loc, GT_EXPR,
1698 boolean_type_node, to, from));
1699 /* If the loop is empty, go directly to the exit label. */
1700 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1701 build1_v (GOTO_EXPR, exit_label),
1702 build_empty_stmt (input_location));
1703 gfc_add_expr_to_block (&block, tmp);
1706 /* Loop body. */
1707 gfc_start_block (&body);
1709 /* Main loop body. */
1710 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1711 gfc_add_expr_to_block (&body, tmp);
1713 /* Label for cycle statements (if needed). */
1714 if (TREE_USED (cycle_label))
1716 tmp = build1_v (LABEL_EXPR, cycle_label);
1717 gfc_add_expr_to_block (&body, tmp);
1720 /* Check whether someone has modified the loop variable. */
1721 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1723 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1724 saved_dovar);
1725 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1726 "Loop variable has been modified");
1729 /* Exit the loop if there is an I/O result condition or error. */
1730 if (exit_cond)
1732 tmp = build1_v (GOTO_EXPR, exit_label);
1733 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1734 exit_cond, tmp,
1735 build_empty_stmt (input_location));
1736 gfc_add_expr_to_block (&body, tmp);
1739 /* Increment the loop variable. */
1740 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1741 gfc_add_modify_loc (loc, &body, dovar, tmp);
1743 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1744 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1746 /* Initialize countm1t. */
1747 tree countm1t = gfc_create_var (utype, "countm1t");
1748 gfc_add_modify_loc (loc, &body, countm1t, countm1);
1750 /* Decrement the loop count. */
1751 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1752 build_int_cst (utype, 1));
1753 gfc_add_modify_loc (loc, &body, countm1, tmp);
1755 /* End with the loop condition. Loop until countm1t == 0. */
1756 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1757 build_int_cst (utype, 0));
1758 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1759 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1760 cond, tmp, build_empty_stmt (loc));
1761 gfc_add_expr_to_block (&body, tmp);
1763 /* End of loop body. */
1764 tmp = gfc_finish_block (&body);
1766 /* The for loop itself. */
1767 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1768 gfc_add_expr_to_block (&block, tmp);
1770 /* Add the exit label. */
1771 tmp = build1_v (LABEL_EXPR, exit_label);
1772 gfc_add_expr_to_block (&block, tmp);
1774 return gfc_finish_block (&block);
1778 /* Translate the DO WHILE construct.
1780 We translate
1782 DO WHILE (cond)
1783 body
1784 END DO
1788 for ( ; ; )
1790 pre_cond;
1791 if (! cond) goto exit_label;
1792 body;
1793 cycle_label:
1795 exit_label:
1797 Because the evaluation of the exit condition `cond' may have side
1798 effects, we can't do much for empty loop bodies. The backend optimizers
1799 should be smart enough to eliminate any dead loops. */
1801 tree
1802 gfc_trans_do_while (gfc_code * code)
1804 gfc_se cond;
1805 tree tmp;
1806 tree cycle_label;
1807 tree exit_label;
1808 stmtblock_t block;
1810 /* Everything we build here is part of the loop body. */
1811 gfc_start_block (&block);
1813 /* Cycle and exit statements are implemented with gotos. */
1814 cycle_label = gfc_build_label_decl (NULL_TREE);
1815 exit_label = gfc_build_label_decl (NULL_TREE);
1817 /* Put the labels where they can be found later. See gfc_trans_do(). */
1818 code->cycle_label = cycle_label;
1819 code->exit_label = exit_label;
1821 /* Create a GIMPLE version of the exit condition. */
1822 gfc_init_se (&cond, NULL);
1823 gfc_conv_expr_val (&cond, code->expr1);
1824 gfc_add_block_to_block (&block, &cond.pre);
1825 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1826 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
1828 /* Build "IF (! cond) GOTO exit_label". */
1829 tmp = build1_v (GOTO_EXPR, exit_label);
1830 TREE_USED (exit_label) = 1;
1831 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1832 void_type_node, cond.expr, tmp,
1833 build_empty_stmt (code->expr1->where.lb->location));
1834 gfc_add_expr_to_block (&block, tmp);
1836 /* The main body of the loop. */
1837 tmp = gfc_trans_code (code->block->next);
1838 gfc_add_expr_to_block (&block, tmp);
1840 /* Label for cycle statements (if needed). */
1841 if (TREE_USED (cycle_label))
1843 tmp = build1_v (LABEL_EXPR, cycle_label);
1844 gfc_add_expr_to_block (&block, tmp);
1847 /* End of loop body. */
1848 tmp = gfc_finish_block (&block);
1850 gfc_init_block (&block);
1851 /* Build the loop. */
1852 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1853 void_type_node, tmp);
1854 gfc_add_expr_to_block (&block, tmp);
1856 /* Add the exit label. */
1857 tmp = build1_v (LABEL_EXPR, exit_label);
1858 gfc_add_expr_to_block (&block, tmp);
1860 return gfc_finish_block (&block);
1864 /* Translate the SELECT CASE construct for INTEGER case expressions,
1865 without killing all potential optimizations. The problem is that
1866 Fortran allows unbounded cases, but the back-end does not, so we
1867 need to intercept those before we enter the equivalent SWITCH_EXPR
1868 we can build.
1870 For example, we translate this,
1872 SELECT CASE (expr)
1873 CASE (:100,101,105:115)
1874 block_1
1875 CASE (190:199,200:)
1876 block_2
1877 CASE (300)
1878 block_3
1879 CASE DEFAULT
1880 block_4
1881 END SELECT
1883 to the GENERIC equivalent,
1885 switch (expr)
1887 case (minimum value for typeof(expr) ... 100:
1888 case 101:
1889 case 105 ... 114:
1890 block1:
1891 goto end_label;
1893 case 200 ... (maximum value for typeof(expr):
1894 case 190 ... 199:
1895 block2;
1896 goto end_label;
1898 case 300:
1899 block_3;
1900 goto end_label;
1902 default:
1903 block_4;
1904 goto end_label;
1907 end_label: */
1909 static tree
1910 gfc_trans_integer_select (gfc_code * code)
1912 gfc_code *c;
1913 gfc_case *cp;
1914 tree end_label;
1915 tree tmp;
1916 gfc_se se;
1917 stmtblock_t block;
1918 stmtblock_t body;
1920 gfc_start_block (&block);
1922 /* Calculate the switch expression. */
1923 gfc_init_se (&se, NULL);
1924 gfc_conv_expr_val (&se, code->expr1);
1925 gfc_add_block_to_block (&block, &se.pre);
1927 end_label = gfc_build_label_decl (NULL_TREE);
1929 gfc_init_block (&body);
1931 for (c = code->block; c; c = c->block)
1933 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1935 tree low, high;
1936 tree label;
1938 /* Assume it's the default case. */
1939 low = high = NULL_TREE;
1941 if (cp->low)
1943 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1944 cp->low->ts.kind);
1946 /* If there's only a lower bound, set the high bound to the
1947 maximum value of the case expression. */
1948 if (!cp->high)
1949 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1952 if (cp->high)
1954 /* Three cases are possible here:
1956 1) There is no lower bound, e.g. CASE (:N).
1957 2) There is a lower bound .NE. high bound, that is
1958 a case range, e.g. CASE (N:M) where M>N (we make
1959 sure that M>N during type resolution).
1960 3) There is a lower bound, and it has the same value
1961 as the high bound, e.g. CASE (N:N). This is our
1962 internal representation of CASE(N).
1964 In the first and second case, we need to set a value for
1965 high. In the third case, we don't because the GCC middle
1966 end represents a single case value by just letting high be
1967 a NULL_TREE. We can't do that because we need to be able
1968 to represent unbounded cases. */
1970 if (!cp->low
1971 || (cp->low
1972 && mpz_cmp (cp->low->value.integer,
1973 cp->high->value.integer) != 0))
1974 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1975 cp->high->ts.kind);
1977 /* Unbounded case. */
1978 if (!cp->low)
1979 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1982 /* Build a label. */
1983 label = gfc_build_label_decl (NULL_TREE);
1985 /* Add this case label.
1986 Add parameter 'label', make it match GCC backend. */
1987 tmp = build_case_label (low, high, label);
1988 gfc_add_expr_to_block (&body, tmp);
1991 /* Add the statements for this case. */
1992 tmp = gfc_trans_code (c->next);
1993 gfc_add_expr_to_block (&body, tmp);
1995 /* Break to the end of the construct. */
1996 tmp = build1_v (GOTO_EXPR, end_label);
1997 gfc_add_expr_to_block (&body, tmp);
2000 tmp = gfc_finish_block (&body);
2001 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2002 se.expr, tmp, NULL_TREE);
2003 gfc_add_expr_to_block (&block, tmp);
2005 tmp = build1_v (LABEL_EXPR, end_label);
2006 gfc_add_expr_to_block (&block, tmp);
2008 return gfc_finish_block (&block);
2012 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2014 There are only two cases possible here, even though the standard
2015 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2016 .FALSE., and DEFAULT.
2018 We never generate more than two blocks here. Instead, we always
2019 try to eliminate the DEFAULT case. This way, we can translate this
2020 kind of SELECT construct to a simple
2022 if {} else {};
2024 expression in GENERIC. */
2026 static tree
2027 gfc_trans_logical_select (gfc_code * code)
2029 gfc_code *c;
2030 gfc_code *t, *f, *d;
2031 gfc_case *cp;
2032 gfc_se se;
2033 stmtblock_t block;
2035 /* Assume we don't have any cases at all. */
2036 t = f = d = NULL;
2038 /* Now see which ones we actually do have. We can have at most two
2039 cases in a single case list: one for .TRUE. and one for .FALSE.
2040 The default case is always separate. If the cases for .TRUE. and
2041 .FALSE. are in the same case list, the block for that case list
2042 always executed, and we don't generate code a COND_EXPR. */
2043 for (c = code->block; c; c = c->block)
2045 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2047 if (cp->low)
2049 if (cp->low->value.logical == 0) /* .FALSE. */
2050 f = c;
2051 else /* if (cp->value.logical != 0), thus .TRUE. */
2052 t = c;
2054 else
2055 d = c;
2059 /* Start a new block. */
2060 gfc_start_block (&block);
2062 /* Calculate the switch expression. We always need to do this
2063 because it may have side effects. */
2064 gfc_init_se (&se, NULL);
2065 gfc_conv_expr_val (&se, code->expr1);
2066 gfc_add_block_to_block (&block, &se.pre);
2068 if (t == f && t != NULL)
2070 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2071 translate the code for these cases, append it to the current
2072 block. */
2073 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2075 else
2077 tree true_tree, false_tree, stmt;
2079 true_tree = build_empty_stmt (input_location);
2080 false_tree = build_empty_stmt (input_location);
2082 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2083 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2084 make the missing case the default case. */
2085 if (t != NULL && f != NULL)
2086 d = NULL;
2087 else if (d != NULL)
2089 if (t == NULL)
2090 t = d;
2091 else
2092 f = d;
2095 /* Translate the code for each of these blocks, and append it to
2096 the current block. */
2097 if (t != NULL)
2098 true_tree = gfc_trans_code (t->next);
2100 if (f != NULL)
2101 false_tree = gfc_trans_code (f->next);
2103 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2104 se.expr, true_tree, false_tree);
2105 gfc_add_expr_to_block (&block, stmt);
2108 return gfc_finish_block (&block);
2112 /* The jump table types are stored in static variables to avoid
2113 constructing them from scratch every single time. */
2114 static GTY(()) tree select_struct[2];
2116 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2117 Instead of generating compares and jumps, it is far simpler to
2118 generate a data structure describing the cases in order and call a
2119 library subroutine that locates the right case.
2120 This is particularly true because this is the only case where we
2121 might have to dispose of a temporary.
2122 The library subroutine returns a pointer to jump to or NULL if no
2123 branches are to be taken. */
2125 static tree
2126 gfc_trans_character_select (gfc_code *code)
2128 tree init, end_label, tmp, type, case_num, label, fndecl;
2129 stmtblock_t block, body;
2130 gfc_case *cp, *d;
2131 gfc_code *c;
2132 gfc_se se, expr1se;
2133 int n, k;
2134 vec<constructor_elt, va_gc> *inits = NULL;
2136 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2138 /* The jump table types are stored in static variables to avoid
2139 constructing them from scratch every single time. */
2140 static tree ss_string1[2], ss_string1_len[2];
2141 static tree ss_string2[2], ss_string2_len[2];
2142 static tree ss_target[2];
2144 cp = code->block->ext.block.case_list;
2145 while (cp->left != NULL)
2146 cp = cp->left;
2148 /* Generate the body */
2149 gfc_start_block (&block);
2150 gfc_init_se (&expr1se, NULL);
2151 gfc_conv_expr_reference (&expr1se, code->expr1);
2153 gfc_add_block_to_block (&block, &expr1se.pre);
2155 end_label = gfc_build_label_decl (NULL_TREE);
2157 gfc_init_block (&body);
2159 /* Attempt to optimize length 1 selects. */
2160 if (integer_onep (expr1se.string_length))
2162 for (d = cp; d; d = d->right)
2164 int i;
2165 if (d->low)
2167 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2168 && d->low->ts.type == BT_CHARACTER);
2169 if (d->low->value.character.length > 1)
2171 for (i = 1; i < d->low->value.character.length; i++)
2172 if (d->low->value.character.string[i] != ' ')
2173 break;
2174 if (i != d->low->value.character.length)
2176 if (optimize && d->high && i == 1)
2178 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2179 && d->high->ts.type == BT_CHARACTER);
2180 if (d->high->value.character.length > 1
2181 && (d->low->value.character.string[0]
2182 == d->high->value.character.string[0])
2183 && d->high->value.character.string[1] != ' '
2184 && ((d->low->value.character.string[1] < ' ')
2185 == (d->high->value.character.string[1]
2186 < ' ')))
2187 continue;
2189 break;
2193 if (d->high)
2195 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2196 && d->high->ts.type == BT_CHARACTER);
2197 if (d->high->value.character.length > 1)
2199 for (i = 1; i < d->high->value.character.length; i++)
2200 if (d->high->value.character.string[i] != ' ')
2201 break;
2202 if (i != d->high->value.character.length)
2203 break;
2207 if (d == NULL)
2209 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2211 for (c = code->block; c; c = c->block)
2213 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2215 tree low, high;
2216 tree label;
2217 gfc_char_t r;
2219 /* Assume it's the default case. */
2220 low = high = NULL_TREE;
2222 if (cp->low)
2224 /* CASE ('ab') or CASE ('ab':'az') will never match
2225 any length 1 character. */
2226 if (cp->low->value.character.length > 1
2227 && cp->low->value.character.string[1] != ' ')
2228 continue;
2230 if (cp->low->value.character.length > 0)
2231 r = cp->low->value.character.string[0];
2232 else
2233 r = ' ';
2234 low = build_int_cst (ctype, r);
2236 /* If there's only a lower bound, set the high bound
2237 to the maximum value of the case expression. */
2238 if (!cp->high)
2239 high = TYPE_MAX_VALUE (ctype);
2242 if (cp->high)
2244 if (!cp->low
2245 || (cp->low->value.character.string[0]
2246 != cp->high->value.character.string[0]))
2248 if (cp->high->value.character.length > 0)
2249 r = cp->high->value.character.string[0];
2250 else
2251 r = ' ';
2252 high = build_int_cst (ctype, r);
2255 /* Unbounded case. */
2256 if (!cp->low)
2257 low = TYPE_MIN_VALUE (ctype);
2260 /* Build a label. */
2261 label = gfc_build_label_decl (NULL_TREE);
2263 /* Add this case label.
2264 Add parameter 'label', make it match GCC backend. */
2265 tmp = build_case_label (low, high, label);
2266 gfc_add_expr_to_block (&body, tmp);
2269 /* Add the statements for this case. */
2270 tmp = gfc_trans_code (c->next);
2271 gfc_add_expr_to_block (&body, tmp);
2273 /* Break to the end of the construct. */
2274 tmp = build1_v (GOTO_EXPR, end_label);
2275 gfc_add_expr_to_block (&body, tmp);
2278 tmp = gfc_string_to_single_character (expr1se.string_length,
2279 expr1se.expr,
2280 code->expr1->ts.kind);
2281 case_num = gfc_create_var (ctype, "case_num");
2282 gfc_add_modify (&block, case_num, tmp);
2284 gfc_add_block_to_block (&block, &expr1se.post);
2286 tmp = gfc_finish_block (&body);
2287 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2288 case_num, tmp, NULL_TREE);
2289 gfc_add_expr_to_block (&block, tmp);
2291 tmp = build1_v (LABEL_EXPR, end_label);
2292 gfc_add_expr_to_block (&block, tmp);
2294 return gfc_finish_block (&block);
2298 if (code->expr1->ts.kind == 1)
2299 k = 0;
2300 else if (code->expr1->ts.kind == 4)
2301 k = 1;
2302 else
2303 gcc_unreachable ();
2305 if (select_struct[k] == NULL)
2307 tree *chain = NULL;
2308 select_struct[k] = make_node (RECORD_TYPE);
2310 if (code->expr1->ts.kind == 1)
2311 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2312 else if (code->expr1->ts.kind == 4)
2313 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2314 else
2315 gcc_unreachable ();
2317 #undef ADD_FIELD
2318 #define ADD_FIELD(NAME, TYPE) \
2319 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2320 get_identifier (stringize(NAME)), \
2321 TYPE, \
2322 &chain)
2324 ADD_FIELD (string1, pchartype);
2325 ADD_FIELD (string1_len, gfc_charlen_type_node);
2327 ADD_FIELD (string2, pchartype);
2328 ADD_FIELD (string2_len, gfc_charlen_type_node);
2330 ADD_FIELD (target, integer_type_node);
2331 #undef ADD_FIELD
2333 gfc_finish_type (select_struct[k]);
2336 n = 0;
2337 for (d = cp; d; d = d->right)
2338 d->n = n++;
2340 for (c = code->block; c; c = c->block)
2342 for (d = c->ext.block.case_list; d; d = d->next)
2344 label = gfc_build_label_decl (NULL_TREE);
2345 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2346 ? NULL
2347 : build_int_cst (integer_type_node, d->n),
2348 NULL, label);
2349 gfc_add_expr_to_block (&body, tmp);
2352 tmp = gfc_trans_code (c->next);
2353 gfc_add_expr_to_block (&body, tmp);
2355 tmp = build1_v (GOTO_EXPR, end_label);
2356 gfc_add_expr_to_block (&body, tmp);
2359 /* Generate the structure describing the branches */
2360 for (d = cp; d; d = d->right)
2362 vec<constructor_elt, va_gc> *node = NULL;
2364 gfc_init_se (&se, NULL);
2366 if (d->low == NULL)
2368 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2369 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2371 else
2373 gfc_conv_expr_reference (&se, d->low);
2375 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2376 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2379 if (d->high == NULL)
2381 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2382 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2384 else
2386 gfc_init_se (&se, NULL);
2387 gfc_conv_expr_reference (&se, d->high);
2389 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2390 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2393 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2394 build_int_cst (integer_type_node, d->n));
2396 tmp = build_constructor (select_struct[k], node);
2397 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2400 type = build_array_type (select_struct[k],
2401 build_index_type (size_int (n-1)));
2403 init = build_constructor (type, inits);
2404 TREE_CONSTANT (init) = 1;
2405 TREE_STATIC (init) = 1;
2406 /* Create a static variable to hold the jump table. */
2407 tmp = gfc_create_var (type, "jumptable");
2408 TREE_CONSTANT (tmp) = 1;
2409 TREE_STATIC (tmp) = 1;
2410 TREE_READONLY (tmp) = 1;
2411 DECL_INITIAL (tmp) = init;
2412 init = tmp;
2414 /* Build the library call */
2415 init = gfc_build_addr_expr (pvoid_type_node, init);
2417 if (code->expr1->ts.kind == 1)
2418 fndecl = gfor_fndecl_select_string;
2419 else if (code->expr1->ts.kind == 4)
2420 fndecl = gfor_fndecl_select_string_char4;
2421 else
2422 gcc_unreachable ();
2424 tmp = build_call_expr_loc (input_location,
2425 fndecl, 4, init,
2426 build_int_cst (gfc_charlen_type_node, n),
2427 expr1se.expr, expr1se.string_length);
2428 case_num = gfc_create_var (integer_type_node, "case_num");
2429 gfc_add_modify (&block, case_num, tmp);
2431 gfc_add_block_to_block (&block, &expr1se.post);
2433 tmp = gfc_finish_block (&body);
2434 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2435 case_num, tmp, NULL_TREE);
2436 gfc_add_expr_to_block (&block, tmp);
2438 tmp = build1_v (LABEL_EXPR, end_label);
2439 gfc_add_expr_to_block (&block, tmp);
2441 return gfc_finish_block (&block);
2445 /* Translate the three variants of the SELECT CASE construct.
2447 SELECT CASEs with INTEGER case expressions can be translated to an
2448 equivalent GENERIC switch statement, and for LOGICAL case
2449 expressions we build one or two if-else compares.
2451 SELECT CASEs with CHARACTER case expressions are a whole different
2452 story, because they don't exist in GENERIC. So we sort them and
2453 do a binary search at runtime.
2455 Fortran has no BREAK statement, and it does not allow jumps from
2456 one case block to another. That makes things a lot easier for
2457 the optimizers. */
2459 tree
2460 gfc_trans_select (gfc_code * code)
2462 stmtblock_t block;
2463 tree body;
2464 tree exit_label;
2466 gcc_assert (code && code->expr1);
2467 gfc_init_block (&block);
2469 /* Build the exit label and hang it in. */
2470 exit_label = gfc_build_label_decl (NULL_TREE);
2471 code->exit_label = exit_label;
2473 /* Empty SELECT constructs are legal. */
2474 if (code->block == NULL)
2475 body = build_empty_stmt (input_location);
2477 /* Select the correct translation function. */
2478 else
2479 switch (code->expr1->ts.type)
2481 case BT_LOGICAL:
2482 body = gfc_trans_logical_select (code);
2483 break;
2485 case BT_INTEGER:
2486 body = gfc_trans_integer_select (code);
2487 break;
2489 case BT_CHARACTER:
2490 body = gfc_trans_character_select (code);
2491 break;
2493 default:
2494 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2495 /* Not reached */
2498 /* Build everything together. */
2499 gfc_add_expr_to_block (&block, body);
2500 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2502 return gfc_finish_block (&block);
2506 /* Traversal function to substitute a replacement symtree if the symbol
2507 in the expression is the same as that passed. f == 2 signals that
2508 that variable itself is not to be checked - only the references.
2509 This group of functions is used when the variable expression in a
2510 FORALL assignment has internal references. For example:
2511 FORALL (i = 1:4) p(p(i)) = i
2512 The only recourse here is to store a copy of 'p' for the index
2513 expression. */
2515 static gfc_symtree *new_symtree;
2516 static gfc_symtree *old_symtree;
2518 static bool
2519 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2521 if (expr->expr_type != EXPR_VARIABLE)
2522 return false;
2524 if (*f == 2)
2525 *f = 1;
2526 else if (expr->symtree->n.sym == sym)
2527 expr->symtree = new_symtree;
2529 return false;
2532 static void
2533 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2535 gfc_traverse_expr (e, sym, forall_replace, f);
2538 static bool
2539 forall_restore (gfc_expr *expr,
2540 gfc_symbol *sym ATTRIBUTE_UNUSED,
2541 int *f ATTRIBUTE_UNUSED)
2543 if (expr->expr_type != EXPR_VARIABLE)
2544 return false;
2546 if (expr->symtree == new_symtree)
2547 expr->symtree = old_symtree;
2549 return false;
2552 static void
2553 forall_restore_symtree (gfc_expr *e)
2555 gfc_traverse_expr (e, NULL, forall_restore, 0);
2558 static void
2559 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2561 gfc_se tse;
2562 gfc_se rse;
2563 gfc_expr *e;
2564 gfc_symbol *new_sym;
2565 gfc_symbol *old_sym;
2566 gfc_symtree *root;
2567 tree tmp;
2569 /* Build a copy of the lvalue. */
2570 old_symtree = c->expr1->symtree;
2571 old_sym = old_symtree->n.sym;
2572 e = gfc_lval_expr_from_sym (old_sym);
2573 if (old_sym->attr.dimension)
2575 gfc_init_se (&tse, NULL);
2576 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2577 gfc_add_block_to_block (pre, &tse.pre);
2578 gfc_add_block_to_block (post, &tse.post);
2579 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2581 if (e->ts.type != BT_CHARACTER)
2583 /* Use the variable offset for the temporary. */
2584 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2585 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2588 else
2590 gfc_init_se (&tse, NULL);
2591 gfc_init_se (&rse, NULL);
2592 gfc_conv_expr (&rse, e);
2593 if (e->ts.type == BT_CHARACTER)
2595 tse.string_length = rse.string_length;
2596 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2597 tse.string_length);
2598 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2599 rse.string_length);
2600 gfc_add_block_to_block (pre, &tse.pre);
2601 gfc_add_block_to_block (post, &tse.post);
2603 else
2605 tmp = gfc_typenode_for_spec (&e->ts);
2606 tse.expr = gfc_create_var (tmp, "temp");
2609 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2610 e->expr_type == EXPR_VARIABLE, true);
2611 gfc_add_expr_to_block (pre, tmp);
2613 gfc_free_expr (e);
2615 /* Create a new symbol to represent the lvalue. */
2616 new_sym = gfc_new_symbol (old_sym->name, NULL);
2617 new_sym->ts = old_sym->ts;
2618 new_sym->attr.referenced = 1;
2619 new_sym->attr.temporary = 1;
2620 new_sym->attr.dimension = old_sym->attr.dimension;
2621 new_sym->attr.flavor = old_sym->attr.flavor;
2623 /* Use the temporary as the backend_decl. */
2624 new_sym->backend_decl = tse.expr;
2626 /* Create a fake symtree for it. */
2627 root = NULL;
2628 new_symtree = gfc_new_symtree (&root, old_sym->name);
2629 new_symtree->n.sym = new_sym;
2630 gcc_assert (new_symtree == root);
2632 /* Go through the expression reference replacing the old_symtree
2633 with the new. */
2634 forall_replace_symtree (c->expr1, old_sym, 2);
2636 /* Now we have made this temporary, we might as well use it for
2637 the right hand side. */
2638 forall_replace_symtree (c->expr2, old_sym, 1);
2642 /* Handles dependencies in forall assignments. */
2643 static int
2644 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2646 gfc_ref *lref;
2647 gfc_ref *rref;
2648 int need_temp;
2649 gfc_symbol *lsym;
2651 lsym = c->expr1->symtree->n.sym;
2652 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2654 /* Now check for dependencies within the 'variable'
2655 expression itself. These are treated by making a complete
2656 copy of variable and changing all the references to it
2657 point to the copy instead. Note that the shallow copy of
2658 the variable will not suffice for derived types with
2659 pointer components. We therefore leave these to their
2660 own devices. */
2661 if (lsym->ts.type == BT_DERIVED
2662 && lsym->ts.u.derived->attr.pointer_comp)
2663 return need_temp;
2665 new_symtree = NULL;
2666 if (find_forall_index (c->expr1, lsym, 2))
2668 forall_make_variable_temp (c, pre, post);
2669 need_temp = 0;
2672 /* Substrings with dependencies are treated in the same
2673 way. */
2674 if (c->expr1->ts.type == BT_CHARACTER
2675 && c->expr1->ref
2676 && c->expr2->expr_type == EXPR_VARIABLE
2677 && lsym == c->expr2->symtree->n.sym)
2679 for (lref = c->expr1->ref; lref; lref = lref->next)
2680 if (lref->type == REF_SUBSTRING)
2681 break;
2682 for (rref = c->expr2->ref; rref; rref = rref->next)
2683 if (rref->type == REF_SUBSTRING)
2684 break;
2686 if (rref && lref
2687 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2689 forall_make_variable_temp (c, pre, post);
2690 need_temp = 0;
2693 return need_temp;
2697 static void
2698 cleanup_forall_symtrees (gfc_code *c)
2700 forall_restore_symtree (c->expr1);
2701 forall_restore_symtree (c->expr2);
2702 free (new_symtree->n.sym);
2703 free (new_symtree);
2707 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2708 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2709 indicates whether we should generate code to test the FORALLs mask
2710 array. OUTER is the loop header to be used for initializing mask
2711 indices.
2713 The generated loop format is:
2714 count = (end - start + step) / step
2715 loopvar = start
2716 while (1)
2718 if (count <=0 )
2719 goto end_of_loop
2720 <body>
2721 loopvar += step
2722 count --
2724 end_of_loop: */
2726 static tree
2727 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2728 int mask_flag, stmtblock_t *outer)
2730 int n, nvar;
2731 tree tmp;
2732 tree cond;
2733 stmtblock_t block;
2734 tree exit_label;
2735 tree count;
2736 tree var, start, end, step;
2737 iter_info *iter;
2739 /* Initialize the mask index outside the FORALL nest. */
2740 if (mask_flag && forall_tmp->mask)
2741 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2743 iter = forall_tmp->this_loop;
2744 nvar = forall_tmp->nvar;
2745 for (n = 0; n < nvar; n++)
2747 var = iter->var;
2748 start = iter->start;
2749 end = iter->end;
2750 step = iter->step;
2752 exit_label = gfc_build_label_decl (NULL_TREE);
2753 TREE_USED (exit_label) = 1;
2755 /* The loop counter. */
2756 count = gfc_create_var (TREE_TYPE (var), "count");
2758 /* The body of the loop. */
2759 gfc_init_block (&block);
2761 /* The exit condition. */
2762 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2763 count, build_int_cst (TREE_TYPE (count), 0));
2764 if (forall_tmp->do_concurrent)
2765 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2766 build_int_cst (integer_type_node,
2767 annot_expr_ivdep_kind));
2769 tmp = build1_v (GOTO_EXPR, exit_label);
2770 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2771 cond, tmp, build_empty_stmt (input_location));
2772 gfc_add_expr_to_block (&block, tmp);
2774 /* The main loop body. */
2775 gfc_add_expr_to_block (&block, body);
2777 /* Increment the loop variable. */
2778 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2779 step);
2780 gfc_add_modify (&block, var, tmp);
2782 /* Advance to the next mask element. Only do this for the
2783 innermost loop. */
2784 if (n == 0 && mask_flag && forall_tmp->mask)
2786 tree maskindex = forall_tmp->maskindex;
2787 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2788 maskindex, gfc_index_one_node);
2789 gfc_add_modify (&block, maskindex, tmp);
2792 /* Decrement the loop counter. */
2793 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2794 build_int_cst (TREE_TYPE (var), 1));
2795 gfc_add_modify (&block, count, tmp);
2797 body = gfc_finish_block (&block);
2799 /* Loop var initialization. */
2800 gfc_init_block (&block);
2801 gfc_add_modify (&block, var, start);
2804 /* Initialize the loop counter. */
2805 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2806 start);
2807 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2808 tmp);
2809 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2810 tmp, step);
2811 gfc_add_modify (&block, count, tmp);
2813 /* The loop expression. */
2814 tmp = build1_v (LOOP_EXPR, body);
2815 gfc_add_expr_to_block (&block, tmp);
2817 /* The exit label. */
2818 tmp = build1_v (LABEL_EXPR, exit_label);
2819 gfc_add_expr_to_block (&block, tmp);
2821 body = gfc_finish_block (&block);
2822 iter = iter->next;
2824 return body;
2828 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2829 is nonzero, the body is controlled by all masks in the forall nest.
2830 Otherwise, the innermost loop is not controlled by it's mask. This
2831 is used for initializing that mask. */
2833 static tree
2834 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2835 int mask_flag)
2837 tree tmp;
2838 stmtblock_t header;
2839 forall_info *forall_tmp;
2840 tree mask, maskindex;
2842 gfc_start_block (&header);
2844 forall_tmp = nested_forall_info;
2845 while (forall_tmp != NULL)
2847 /* Generate body with masks' control. */
2848 if (mask_flag)
2850 mask = forall_tmp->mask;
2851 maskindex = forall_tmp->maskindex;
2853 /* If a mask was specified make the assignment conditional. */
2854 if (mask)
2856 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2857 body = build3_v (COND_EXPR, tmp, body,
2858 build_empty_stmt (input_location));
2861 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2862 forall_tmp = forall_tmp->prev_nest;
2863 mask_flag = 1;
2866 gfc_add_expr_to_block (&header, body);
2867 return gfc_finish_block (&header);
2871 /* Allocate data for holding a temporary array. Returns either a local
2872 temporary array or a pointer variable. */
2874 static tree
2875 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2876 tree elem_type)
2878 tree tmpvar;
2879 tree type;
2880 tree tmp;
2882 if (INTEGER_CST_P (size))
2883 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2884 size, gfc_index_one_node);
2885 else
2886 tmp = NULL_TREE;
2888 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2889 type = build_array_type (elem_type, type);
2890 if (gfc_can_put_var_on_stack (bytesize))
2892 gcc_assert (INTEGER_CST_P (size));
2893 tmpvar = gfc_create_var (type, "temp");
2894 *pdata = NULL_TREE;
2896 else
2898 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2899 *pdata = convert (pvoid_type_node, tmpvar);
2901 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2902 gfc_add_modify (pblock, tmpvar, tmp);
2904 return tmpvar;
2908 /* Generate codes to copy the temporary to the actual lhs. */
2910 static tree
2911 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2912 tree count1, tree wheremask, bool invert)
2914 gfc_ss *lss;
2915 gfc_se lse, rse;
2916 stmtblock_t block, body;
2917 gfc_loopinfo loop1;
2918 tree tmp;
2919 tree wheremaskexpr;
2921 /* Walk the lhs. */
2922 lss = gfc_walk_expr (expr);
2924 if (lss == gfc_ss_terminator)
2926 gfc_start_block (&block);
2928 gfc_init_se (&lse, NULL);
2930 /* Translate the expression. */
2931 gfc_conv_expr (&lse, expr);
2933 /* Form the expression for the temporary. */
2934 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2936 /* Use the scalar assignment as is. */
2937 gfc_add_block_to_block (&block, &lse.pre);
2938 gfc_add_modify (&block, lse.expr, tmp);
2939 gfc_add_block_to_block (&block, &lse.post);
2941 /* Increment the count1. */
2942 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2943 count1, gfc_index_one_node);
2944 gfc_add_modify (&block, count1, tmp);
2946 tmp = gfc_finish_block (&block);
2948 else
2950 gfc_start_block (&block);
2952 gfc_init_loopinfo (&loop1);
2953 gfc_init_se (&rse, NULL);
2954 gfc_init_se (&lse, NULL);
2956 /* Associate the lss with the loop. */
2957 gfc_add_ss_to_loop (&loop1, lss);
2959 /* Calculate the bounds of the scalarization. */
2960 gfc_conv_ss_startstride (&loop1);
2961 /* Setup the scalarizing loops. */
2962 gfc_conv_loop_setup (&loop1, &expr->where);
2964 gfc_mark_ss_chain_used (lss, 1);
2966 /* Start the scalarized loop body. */
2967 gfc_start_scalarized_body (&loop1, &body);
2969 /* Setup the gfc_se structures. */
2970 gfc_copy_loopinfo_to_se (&lse, &loop1);
2971 lse.ss = lss;
2973 /* Form the expression of the temporary. */
2974 if (lss != gfc_ss_terminator)
2975 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2976 /* Translate expr. */
2977 gfc_conv_expr (&lse, expr);
2979 /* Use the scalar assignment. */
2980 rse.string_length = lse.string_length;
2981 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
2983 /* Form the mask expression according to the mask tree list. */
2984 if (wheremask)
2986 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2987 if (invert)
2988 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2989 TREE_TYPE (wheremaskexpr),
2990 wheremaskexpr);
2991 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2992 wheremaskexpr, tmp,
2993 build_empty_stmt (input_location));
2996 gfc_add_expr_to_block (&body, tmp);
2998 /* Increment count1. */
2999 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3000 count1, gfc_index_one_node);
3001 gfc_add_modify (&body, count1, tmp);
3003 /* Increment count3. */
3004 if (count3)
3006 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3007 gfc_array_index_type, count3,
3008 gfc_index_one_node);
3009 gfc_add_modify (&body, count3, tmp);
3012 /* Generate the copying loops. */
3013 gfc_trans_scalarizing_loops (&loop1, &body);
3014 gfc_add_block_to_block (&block, &loop1.pre);
3015 gfc_add_block_to_block (&block, &loop1.post);
3016 gfc_cleanup_loop (&loop1);
3018 tmp = gfc_finish_block (&block);
3020 return tmp;
3024 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3025 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3026 and should not be freed. WHEREMASK is the conditional execution mask
3027 whose sense may be inverted by INVERT. */
3029 static tree
3030 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3031 tree count1, gfc_ss *lss, gfc_ss *rss,
3032 tree wheremask, bool invert)
3034 stmtblock_t block, body1;
3035 gfc_loopinfo loop;
3036 gfc_se lse;
3037 gfc_se rse;
3038 tree tmp;
3039 tree wheremaskexpr;
3041 gfc_start_block (&block);
3043 gfc_init_se (&rse, NULL);
3044 gfc_init_se (&lse, NULL);
3046 if (lss == gfc_ss_terminator)
3048 gfc_init_block (&body1);
3049 gfc_conv_expr (&rse, expr2);
3050 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3052 else
3054 /* Initialize the loop. */
3055 gfc_init_loopinfo (&loop);
3057 /* We may need LSS to determine the shape of the expression. */
3058 gfc_add_ss_to_loop (&loop, lss);
3059 gfc_add_ss_to_loop (&loop, rss);
3061 gfc_conv_ss_startstride (&loop);
3062 gfc_conv_loop_setup (&loop, &expr2->where);
3064 gfc_mark_ss_chain_used (rss, 1);
3065 /* Start the loop body. */
3066 gfc_start_scalarized_body (&loop, &body1);
3068 /* Translate the expression. */
3069 gfc_copy_loopinfo_to_se (&rse, &loop);
3070 rse.ss = rss;
3071 gfc_conv_expr (&rse, expr2);
3073 /* Form the expression of the temporary. */
3074 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3077 /* Use the scalar assignment. */
3078 lse.string_length = rse.string_length;
3079 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3080 expr2->expr_type == EXPR_VARIABLE, true);
3082 /* Form the mask expression according to the mask tree list. */
3083 if (wheremask)
3085 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3086 if (invert)
3087 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3088 TREE_TYPE (wheremaskexpr),
3089 wheremaskexpr);
3090 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3091 wheremaskexpr, tmp,
3092 build_empty_stmt (input_location));
3095 gfc_add_expr_to_block (&body1, tmp);
3097 if (lss == gfc_ss_terminator)
3099 gfc_add_block_to_block (&block, &body1);
3101 /* Increment count1. */
3102 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3103 count1, gfc_index_one_node);
3104 gfc_add_modify (&block, count1, tmp);
3106 else
3108 /* Increment count1. */
3109 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3110 count1, gfc_index_one_node);
3111 gfc_add_modify (&body1, count1, tmp);
3113 /* Increment count3. */
3114 if (count3)
3116 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3117 gfc_array_index_type,
3118 count3, gfc_index_one_node);
3119 gfc_add_modify (&body1, count3, tmp);
3122 /* Generate the copying loops. */
3123 gfc_trans_scalarizing_loops (&loop, &body1);
3125 gfc_add_block_to_block (&block, &loop.pre);
3126 gfc_add_block_to_block (&block, &loop.post);
3128 gfc_cleanup_loop (&loop);
3129 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3130 as tree nodes in SS may not be valid in different scope. */
3133 tmp = gfc_finish_block (&block);
3134 return tmp;
3138 /* Calculate the size of temporary needed in the assignment inside forall.
3139 LSS and RSS are filled in this function. */
3141 static tree
3142 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3143 stmtblock_t * pblock,
3144 gfc_ss **lss, gfc_ss **rss)
3146 gfc_loopinfo loop;
3147 tree size;
3148 int i;
3149 int save_flag;
3150 tree tmp;
3152 *lss = gfc_walk_expr (expr1);
3153 *rss = NULL;
3155 size = gfc_index_one_node;
3156 if (*lss != gfc_ss_terminator)
3158 gfc_init_loopinfo (&loop);
3160 /* Walk the RHS of the expression. */
3161 *rss = gfc_walk_expr (expr2);
3162 if (*rss == gfc_ss_terminator)
3163 /* The rhs is scalar. Add a ss for the expression. */
3164 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3166 /* Associate the SS with the loop. */
3167 gfc_add_ss_to_loop (&loop, *lss);
3168 /* We don't actually need to add the rhs at this point, but it might
3169 make guessing the loop bounds a bit easier. */
3170 gfc_add_ss_to_loop (&loop, *rss);
3172 /* We only want the shape of the expression, not rest of the junk
3173 generated by the scalarizer. */
3174 loop.array_parameter = 1;
3176 /* Calculate the bounds of the scalarization. */
3177 save_flag = gfc_option.rtcheck;
3178 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3179 gfc_conv_ss_startstride (&loop);
3180 gfc_option.rtcheck = save_flag;
3181 gfc_conv_loop_setup (&loop, &expr2->where);
3183 /* Figure out how many elements we need. */
3184 for (i = 0; i < loop.dimen; i++)
3186 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3187 gfc_array_index_type,
3188 gfc_index_one_node, loop.from[i]);
3189 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3190 gfc_array_index_type, tmp, loop.to[i]);
3191 size = fold_build2_loc (input_location, MULT_EXPR,
3192 gfc_array_index_type, size, tmp);
3194 gfc_add_block_to_block (pblock, &loop.pre);
3195 size = gfc_evaluate_now (size, pblock);
3196 gfc_add_block_to_block (pblock, &loop.post);
3198 /* TODO: write a function that cleans up a loopinfo without freeing
3199 the SS chains. Currently a NOP. */
3202 return size;
3206 /* Calculate the overall iterator number of the nested forall construct.
3207 This routine actually calculates the number of times the body of the
3208 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3209 that by the expression INNER_SIZE. The BLOCK argument specifies the
3210 block in which to calculate the result, and the optional INNER_SIZE_BODY
3211 argument contains any statements that need to executed (inside the loop)
3212 to initialize or calculate INNER_SIZE. */
3214 static tree
3215 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3216 stmtblock_t *inner_size_body, stmtblock_t *block)
3218 forall_info *forall_tmp = nested_forall_info;
3219 tree tmp, number;
3220 stmtblock_t body;
3222 /* We can eliminate the innermost unconditional loops with constant
3223 array bounds. */
3224 if (INTEGER_CST_P (inner_size))
3226 while (forall_tmp
3227 && !forall_tmp->mask
3228 && INTEGER_CST_P (forall_tmp->size))
3230 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3231 gfc_array_index_type,
3232 inner_size, forall_tmp->size);
3233 forall_tmp = forall_tmp->prev_nest;
3236 /* If there are no loops left, we have our constant result. */
3237 if (!forall_tmp)
3238 return inner_size;
3241 /* Otherwise, create a temporary variable to compute the result. */
3242 number = gfc_create_var (gfc_array_index_type, "num");
3243 gfc_add_modify (block, number, gfc_index_zero_node);
3245 gfc_start_block (&body);
3246 if (inner_size_body)
3247 gfc_add_block_to_block (&body, inner_size_body);
3248 if (forall_tmp)
3249 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3250 gfc_array_index_type, number, inner_size);
3251 else
3252 tmp = inner_size;
3253 gfc_add_modify (&body, number, tmp);
3254 tmp = gfc_finish_block (&body);
3256 /* Generate loops. */
3257 if (forall_tmp != NULL)
3258 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3260 gfc_add_expr_to_block (block, tmp);
3262 return number;
3266 /* Allocate temporary for forall construct. SIZE is the size of temporary
3267 needed. PTEMP1 is returned for space free. */
3269 static tree
3270 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3271 tree * ptemp1)
3273 tree bytesize;
3274 tree unit;
3275 tree tmp;
3277 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3278 if (!integer_onep (unit))
3279 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3280 gfc_array_index_type, size, unit);
3281 else
3282 bytesize = size;
3284 *ptemp1 = NULL;
3285 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3287 if (*ptemp1)
3288 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3289 return tmp;
3293 /* Allocate temporary for forall construct according to the information in
3294 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3295 assignment inside forall. PTEMP1 is returned for space free. */
3297 static tree
3298 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3299 tree inner_size, stmtblock_t * inner_size_body,
3300 stmtblock_t * block, tree * ptemp1)
3302 tree size;
3304 /* Calculate the total size of temporary needed in forall construct. */
3305 size = compute_overall_iter_number (nested_forall_info, inner_size,
3306 inner_size_body, block);
3308 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3312 /* Handle assignments inside forall which need temporary.
3314 forall (i=start:end:stride; maskexpr)
3315 e<i> = f<i>
3316 end forall
3317 (where e,f<i> are arbitrary expressions possibly involving i
3318 and there is a dependency between e<i> and f<i>)
3319 Translates to:
3320 masktmp(:) = maskexpr(:)
3322 maskindex = 0;
3323 count1 = 0;
3324 num = 0;
3325 for (i = start; i <= end; i += stride)
3326 num += SIZE (f<i>)
3327 count1 = 0;
3328 ALLOCATE (tmp(num))
3329 for (i = start; i <= end; i += stride)
3331 if (masktmp[maskindex++])
3332 tmp[count1++] = f<i>
3334 maskindex = 0;
3335 count1 = 0;
3336 for (i = start; i <= end; i += stride)
3338 if (masktmp[maskindex++])
3339 e<i> = tmp[count1++]
3341 DEALLOCATE (tmp)
3343 static void
3344 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3345 tree wheremask, bool invert,
3346 forall_info * nested_forall_info,
3347 stmtblock_t * block)
3349 tree type;
3350 tree inner_size;
3351 gfc_ss *lss, *rss;
3352 tree count, count1;
3353 tree tmp, tmp1;
3354 tree ptemp1;
3355 stmtblock_t inner_size_body;
3357 /* Create vars. count1 is the current iterator number of the nested
3358 forall. */
3359 count1 = gfc_create_var (gfc_array_index_type, "count1");
3361 /* Count is the wheremask index. */
3362 if (wheremask)
3364 count = gfc_create_var (gfc_array_index_type, "count");
3365 gfc_add_modify (block, count, gfc_index_zero_node);
3367 else
3368 count = NULL;
3370 /* Initialize count1. */
3371 gfc_add_modify (block, count1, gfc_index_zero_node);
3373 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3374 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3375 gfc_init_block (&inner_size_body);
3376 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3377 &lss, &rss);
3379 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3380 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3382 if (!expr1->ts.u.cl->backend_decl)
3384 gfc_se tse;
3385 gfc_init_se (&tse, NULL);
3386 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3387 expr1->ts.u.cl->backend_decl = tse.expr;
3389 type = gfc_get_character_type_len (gfc_default_character_kind,
3390 expr1->ts.u.cl->backend_decl);
3392 else
3393 type = gfc_typenode_for_spec (&expr1->ts);
3395 /* Allocate temporary for nested forall construct according to the
3396 information in nested_forall_info and inner_size. */
3397 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3398 &inner_size_body, block, &ptemp1);
3400 /* Generate codes to copy rhs to the temporary . */
3401 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3402 wheremask, invert);
3404 /* Generate body and loops according to the information in
3405 nested_forall_info. */
3406 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3407 gfc_add_expr_to_block (block, tmp);
3409 /* Reset count1. */
3410 gfc_add_modify (block, count1, gfc_index_zero_node);
3412 /* Reset count. */
3413 if (wheremask)
3414 gfc_add_modify (block, count, gfc_index_zero_node);
3416 /* Generate codes to copy the temporary to lhs. */
3417 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3418 wheremask, invert);
3420 /* Generate body and loops according to the information in
3421 nested_forall_info. */
3422 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3423 gfc_add_expr_to_block (block, tmp);
3425 if (ptemp1)
3427 /* Free the temporary. */
3428 tmp = gfc_call_free (ptemp1);
3429 gfc_add_expr_to_block (block, tmp);
3434 /* Translate pointer assignment inside FORALL which need temporary. */
3436 static void
3437 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3438 forall_info * nested_forall_info,
3439 stmtblock_t * block)
3441 tree type;
3442 tree inner_size;
3443 gfc_ss *lss, *rss;
3444 gfc_se lse;
3445 gfc_se rse;
3446 gfc_array_info *info;
3447 gfc_loopinfo loop;
3448 tree desc;
3449 tree parm;
3450 tree parmtype;
3451 stmtblock_t body;
3452 tree count;
3453 tree tmp, tmp1, ptemp1;
3455 count = gfc_create_var (gfc_array_index_type, "count");
3456 gfc_add_modify (block, count, gfc_index_zero_node);
3458 inner_size = gfc_index_one_node;
3459 lss = gfc_walk_expr (expr1);
3460 rss = gfc_walk_expr (expr2);
3461 if (lss == gfc_ss_terminator)
3463 type = gfc_typenode_for_spec (&expr1->ts);
3464 type = build_pointer_type (type);
3466 /* Allocate temporary for nested forall construct according to the
3467 information in nested_forall_info and inner_size. */
3468 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3469 inner_size, NULL, block, &ptemp1);
3470 gfc_start_block (&body);
3471 gfc_init_se (&lse, NULL);
3472 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3473 gfc_init_se (&rse, NULL);
3474 rse.want_pointer = 1;
3475 gfc_conv_expr (&rse, expr2);
3476 gfc_add_block_to_block (&body, &rse.pre);
3477 gfc_add_modify (&body, lse.expr,
3478 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3479 gfc_add_block_to_block (&body, &rse.post);
3481 /* Increment count. */
3482 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3483 count, gfc_index_one_node);
3484 gfc_add_modify (&body, count, tmp);
3486 tmp = gfc_finish_block (&body);
3488 /* Generate body and loops according to the information in
3489 nested_forall_info. */
3490 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3491 gfc_add_expr_to_block (block, tmp);
3493 /* Reset count. */
3494 gfc_add_modify (block, count, gfc_index_zero_node);
3496 gfc_start_block (&body);
3497 gfc_init_se (&lse, NULL);
3498 gfc_init_se (&rse, NULL);
3499 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3500 lse.want_pointer = 1;
3501 gfc_conv_expr (&lse, expr1);
3502 gfc_add_block_to_block (&body, &lse.pre);
3503 gfc_add_modify (&body, lse.expr, rse.expr);
3504 gfc_add_block_to_block (&body, &lse.post);
3505 /* Increment count. */
3506 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3507 count, gfc_index_one_node);
3508 gfc_add_modify (&body, count, tmp);
3509 tmp = gfc_finish_block (&body);
3511 /* Generate body and loops according to the information in
3512 nested_forall_info. */
3513 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3514 gfc_add_expr_to_block (block, tmp);
3516 else
3518 gfc_init_loopinfo (&loop);
3520 /* Associate the SS with the loop. */
3521 gfc_add_ss_to_loop (&loop, rss);
3523 /* Setup the scalarizing loops and bounds. */
3524 gfc_conv_ss_startstride (&loop);
3526 gfc_conv_loop_setup (&loop, &expr2->where);
3528 info = &rss->info->data.array;
3529 desc = info->descriptor;
3531 /* Make a new descriptor. */
3532 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3533 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3534 loop.from, loop.to, 1,
3535 GFC_ARRAY_UNKNOWN, true);
3537 /* Allocate temporary for nested forall construct. */
3538 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3539 inner_size, NULL, block, &ptemp1);
3540 gfc_start_block (&body);
3541 gfc_init_se (&lse, NULL);
3542 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3543 lse.direct_byref = 1;
3544 gfc_conv_expr_descriptor (&lse, expr2);
3546 gfc_add_block_to_block (&body, &lse.pre);
3547 gfc_add_block_to_block (&body, &lse.post);
3549 /* Increment count. */
3550 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3551 count, gfc_index_one_node);
3552 gfc_add_modify (&body, count, tmp);
3554 tmp = gfc_finish_block (&body);
3556 /* Generate body and loops according to the information in
3557 nested_forall_info. */
3558 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3559 gfc_add_expr_to_block (block, tmp);
3561 /* Reset count. */
3562 gfc_add_modify (block, count, gfc_index_zero_node);
3564 parm = gfc_build_array_ref (tmp1, count, NULL);
3565 gfc_init_se (&lse, NULL);
3566 gfc_conv_expr_descriptor (&lse, expr1);
3567 gfc_add_modify (&lse.pre, lse.expr, parm);
3568 gfc_start_block (&body);
3569 gfc_add_block_to_block (&body, &lse.pre);
3570 gfc_add_block_to_block (&body, &lse.post);
3572 /* Increment count. */
3573 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3574 count, gfc_index_one_node);
3575 gfc_add_modify (&body, count, tmp);
3577 tmp = gfc_finish_block (&body);
3579 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3580 gfc_add_expr_to_block (block, tmp);
3582 /* Free the temporary. */
3583 if (ptemp1)
3585 tmp = gfc_call_free (ptemp1);
3586 gfc_add_expr_to_block (block, tmp);
3591 /* FORALL and WHERE statements are really nasty, especially when you nest
3592 them. All the rhs of a forall assignment must be evaluated before the
3593 actual assignments are performed. Presumably this also applies to all the
3594 assignments in an inner where statement. */
3596 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3597 linear array, relying on the fact that we process in the same order in all
3598 loops.
3600 forall (i=start:end:stride; maskexpr)
3601 e<i> = f<i>
3602 g<i> = h<i>
3603 end forall
3604 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3605 Translates to:
3606 count = ((end + 1 - start) / stride)
3607 masktmp(:) = maskexpr(:)
3609 maskindex = 0;
3610 for (i = start; i <= end; i += stride)
3612 if (masktmp[maskindex++])
3613 e<i> = f<i>
3615 maskindex = 0;
3616 for (i = start; i <= end; i += stride)
3618 if (masktmp[maskindex++])
3619 g<i> = h<i>
3622 Note that this code only works when there are no dependencies.
3623 Forall loop with array assignments and data dependencies are a real pain,
3624 because the size of the temporary cannot always be determined before the
3625 loop is executed. This problem is compounded by the presence of nested
3626 FORALL constructs.
3629 static tree
3630 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3632 stmtblock_t pre;
3633 stmtblock_t post;
3634 stmtblock_t block;
3635 stmtblock_t body;
3636 tree *var;
3637 tree *start;
3638 tree *end;
3639 tree *step;
3640 gfc_expr **varexpr;
3641 tree tmp;
3642 tree assign;
3643 tree size;
3644 tree maskindex;
3645 tree mask;
3646 tree pmask;
3647 tree cycle_label = NULL_TREE;
3648 int n;
3649 int nvar;
3650 int need_temp;
3651 gfc_forall_iterator *fa;
3652 gfc_se se;
3653 gfc_code *c;
3654 gfc_saved_var *saved_vars;
3655 iter_info *this_forall;
3656 forall_info *info;
3657 bool need_mask;
3659 /* Do nothing if the mask is false. */
3660 if (code->expr1
3661 && code->expr1->expr_type == EXPR_CONSTANT
3662 && !code->expr1->value.logical)
3663 return build_empty_stmt (input_location);
3665 n = 0;
3666 /* Count the FORALL index number. */
3667 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3668 n++;
3669 nvar = n;
3671 /* Allocate the space for var, start, end, step, varexpr. */
3672 var = XCNEWVEC (tree, nvar);
3673 start = XCNEWVEC (tree, nvar);
3674 end = XCNEWVEC (tree, nvar);
3675 step = XCNEWVEC (tree, nvar);
3676 varexpr = XCNEWVEC (gfc_expr *, nvar);
3677 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3679 /* Allocate the space for info. */
3680 info = XCNEW (forall_info);
3682 gfc_start_block (&pre);
3683 gfc_init_block (&post);
3684 gfc_init_block (&block);
3686 n = 0;
3687 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3689 gfc_symbol *sym = fa->var->symtree->n.sym;
3691 /* Allocate space for this_forall. */
3692 this_forall = XCNEW (iter_info);
3694 /* Create a temporary variable for the FORALL index. */
3695 tmp = gfc_typenode_for_spec (&sym->ts);
3696 var[n] = gfc_create_var (tmp, sym->name);
3697 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3699 /* Record it in this_forall. */
3700 this_forall->var = var[n];
3702 /* Replace the index symbol's backend_decl with the temporary decl. */
3703 sym->backend_decl = var[n];
3705 /* Work out the start, end and stride for the loop. */
3706 gfc_init_se (&se, NULL);
3707 gfc_conv_expr_val (&se, fa->start);
3708 /* Record it in this_forall. */
3709 this_forall->start = se.expr;
3710 gfc_add_block_to_block (&block, &se.pre);
3711 start[n] = se.expr;
3713 gfc_init_se (&se, NULL);
3714 gfc_conv_expr_val (&se, fa->end);
3715 /* Record it in this_forall. */
3716 this_forall->end = se.expr;
3717 gfc_make_safe_expr (&se);
3718 gfc_add_block_to_block (&block, &se.pre);
3719 end[n] = se.expr;
3721 gfc_init_se (&se, NULL);
3722 gfc_conv_expr_val (&se, fa->stride);
3723 /* Record it in this_forall. */
3724 this_forall->step = se.expr;
3725 gfc_make_safe_expr (&se);
3726 gfc_add_block_to_block (&block, &se.pre);
3727 step[n] = se.expr;
3729 /* Set the NEXT field of this_forall to NULL. */
3730 this_forall->next = NULL;
3731 /* Link this_forall to the info construct. */
3732 if (info->this_loop)
3734 iter_info *iter_tmp = info->this_loop;
3735 while (iter_tmp->next != NULL)
3736 iter_tmp = iter_tmp->next;
3737 iter_tmp->next = this_forall;
3739 else
3740 info->this_loop = this_forall;
3742 n++;
3744 nvar = n;
3746 /* Calculate the size needed for the current forall level. */
3747 size = gfc_index_one_node;
3748 for (n = 0; n < nvar; n++)
3750 /* size = (end + step - start) / step. */
3751 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3752 step[n], start[n]);
3753 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3754 end[n], tmp);
3755 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3756 tmp, step[n]);
3757 tmp = convert (gfc_array_index_type, tmp);
3759 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3760 size, tmp);
3763 /* Record the nvar and size of current forall level. */
3764 info->nvar = nvar;
3765 info->size = size;
3767 if (code->expr1)
3769 /* If the mask is .true., consider the FORALL unconditional. */
3770 if (code->expr1->expr_type == EXPR_CONSTANT
3771 && code->expr1->value.logical)
3772 need_mask = false;
3773 else
3774 need_mask = true;
3776 else
3777 need_mask = false;
3779 /* First we need to allocate the mask. */
3780 if (need_mask)
3782 /* As the mask array can be very big, prefer compact boolean types. */
3783 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3784 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3785 size, NULL, &block, &pmask);
3786 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3788 /* Record them in the info structure. */
3789 info->maskindex = maskindex;
3790 info->mask = mask;
3792 else
3794 /* No mask was specified. */
3795 maskindex = NULL_TREE;
3796 mask = pmask = NULL_TREE;
3799 /* Link the current forall level to nested_forall_info. */
3800 info->prev_nest = nested_forall_info;
3801 nested_forall_info = info;
3803 /* Copy the mask into a temporary variable if required.
3804 For now we assume a mask temporary is needed. */
3805 if (need_mask)
3807 /* As the mask array can be very big, prefer compact boolean types. */
3808 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3810 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3812 /* Start of mask assignment loop body. */
3813 gfc_start_block (&body);
3815 /* Evaluate the mask expression. */
3816 gfc_init_se (&se, NULL);
3817 gfc_conv_expr_val (&se, code->expr1);
3818 gfc_add_block_to_block (&body, &se.pre);
3820 /* Store the mask. */
3821 se.expr = convert (mask_type, se.expr);
3823 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3824 gfc_add_modify (&body, tmp, se.expr);
3826 /* Advance to the next mask element. */
3827 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3828 maskindex, gfc_index_one_node);
3829 gfc_add_modify (&body, maskindex, tmp);
3831 /* Generate the loops. */
3832 tmp = gfc_finish_block (&body);
3833 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3834 gfc_add_expr_to_block (&block, tmp);
3837 if (code->op == EXEC_DO_CONCURRENT)
3839 gfc_init_block (&body);
3840 cycle_label = gfc_build_label_decl (NULL_TREE);
3841 code->cycle_label = cycle_label;
3842 tmp = gfc_trans_code (code->block->next);
3843 gfc_add_expr_to_block (&body, tmp);
3845 if (TREE_USED (cycle_label))
3847 tmp = build1_v (LABEL_EXPR, cycle_label);
3848 gfc_add_expr_to_block (&body, tmp);
3851 tmp = gfc_finish_block (&body);
3852 nested_forall_info->do_concurrent = true;
3853 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3854 gfc_add_expr_to_block (&block, tmp);
3855 goto done;
3858 c = code->block->next;
3860 /* TODO: loop merging in FORALL statements. */
3861 /* Now that we've got a copy of the mask, generate the assignment loops. */
3862 while (c)
3864 switch (c->op)
3866 case EXEC_ASSIGN:
3867 /* A scalar or array assignment. DO the simple check for
3868 lhs to rhs dependencies. These make a temporary for the
3869 rhs and form a second forall block to copy to variable. */
3870 need_temp = check_forall_dependencies(c, &pre, &post);
3872 /* Temporaries due to array assignment data dependencies introduce
3873 no end of problems. */
3874 if (need_temp)
3875 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3876 nested_forall_info, &block);
3877 else
3879 /* Use the normal assignment copying routines. */
3880 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3882 /* Generate body and loops. */
3883 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3884 assign, 1);
3885 gfc_add_expr_to_block (&block, tmp);
3888 /* Cleanup any temporary symtrees that have been made to deal
3889 with dependencies. */
3890 if (new_symtree)
3891 cleanup_forall_symtrees (c);
3893 break;
3895 case EXEC_WHERE:
3896 /* Translate WHERE or WHERE construct nested in FORALL. */
3897 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3898 break;
3900 /* Pointer assignment inside FORALL. */
3901 case EXEC_POINTER_ASSIGN:
3902 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3903 if (need_temp)
3904 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3905 nested_forall_info, &block);
3906 else
3908 /* Use the normal assignment copying routines. */
3909 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3911 /* Generate body and loops. */
3912 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3913 assign, 1);
3914 gfc_add_expr_to_block (&block, tmp);
3916 break;
3918 case EXEC_FORALL:
3919 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3920 gfc_add_expr_to_block (&block, tmp);
3921 break;
3923 /* Explicit subroutine calls are prevented by the frontend but interface
3924 assignments can legitimately produce them. */
3925 case EXEC_ASSIGN_CALL:
3926 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3927 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3928 gfc_add_expr_to_block (&block, tmp);
3929 break;
3931 default:
3932 gcc_unreachable ();
3935 c = c->next;
3938 done:
3939 /* Restore the original index variables. */
3940 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3941 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3943 /* Free the space for var, start, end, step, varexpr. */
3944 free (var);
3945 free (start);
3946 free (end);
3947 free (step);
3948 free (varexpr);
3949 free (saved_vars);
3951 for (this_forall = info->this_loop; this_forall;)
3953 iter_info *next = this_forall->next;
3954 free (this_forall);
3955 this_forall = next;
3958 /* Free the space for this forall_info. */
3959 free (info);
3961 if (pmask)
3963 /* Free the temporary for the mask. */
3964 tmp = gfc_call_free (pmask);
3965 gfc_add_expr_to_block (&block, tmp);
3967 if (maskindex)
3968 pushdecl (maskindex);
3970 gfc_add_block_to_block (&pre, &block);
3971 gfc_add_block_to_block (&pre, &post);
3973 return gfc_finish_block (&pre);
3977 /* Translate the FORALL statement or construct. */
3979 tree gfc_trans_forall (gfc_code * code)
3981 return gfc_trans_forall_1 (code, NULL);
3985 /* Translate the DO CONCURRENT construct. */
3987 tree gfc_trans_do_concurrent (gfc_code * code)
3989 return gfc_trans_forall_1 (code, NULL);
3993 /* Evaluate the WHERE mask expression, copy its value to a temporary.
3994 If the WHERE construct is nested in FORALL, compute the overall temporary
3995 needed by the WHERE mask expression multiplied by the iterator number of
3996 the nested forall.
3997 ME is the WHERE mask expression.
3998 MASK is the current execution mask upon input, whose sense may or may
3999 not be inverted as specified by the INVERT argument.
4000 CMASK is the updated execution mask on output, or NULL if not required.
4001 PMASK is the pending execution mask on output, or NULL if not required.
4002 BLOCK is the block in which to place the condition evaluation loops. */
4004 static void
4005 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4006 tree mask, bool invert, tree cmask, tree pmask,
4007 tree mask_type, stmtblock_t * block)
4009 tree tmp, tmp1;
4010 gfc_ss *lss, *rss;
4011 gfc_loopinfo loop;
4012 stmtblock_t body, body1;
4013 tree count, cond, mtmp;
4014 gfc_se lse, rse;
4016 gfc_init_loopinfo (&loop);
4018 lss = gfc_walk_expr (me);
4019 rss = gfc_walk_expr (me);
4021 /* Variable to index the temporary. */
4022 count = gfc_create_var (gfc_array_index_type, "count");
4023 /* Initialize count. */
4024 gfc_add_modify (block, count, gfc_index_zero_node);
4026 gfc_start_block (&body);
4028 gfc_init_se (&rse, NULL);
4029 gfc_init_se (&lse, NULL);
4031 if (lss == gfc_ss_terminator)
4033 gfc_init_block (&body1);
4035 else
4037 /* Initialize the loop. */
4038 gfc_init_loopinfo (&loop);
4040 /* We may need LSS to determine the shape of the expression. */
4041 gfc_add_ss_to_loop (&loop, lss);
4042 gfc_add_ss_to_loop (&loop, rss);
4044 gfc_conv_ss_startstride (&loop);
4045 gfc_conv_loop_setup (&loop, &me->where);
4047 gfc_mark_ss_chain_used (rss, 1);
4048 /* Start the loop body. */
4049 gfc_start_scalarized_body (&loop, &body1);
4051 /* Translate the expression. */
4052 gfc_copy_loopinfo_to_se (&rse, &loop);
4053 rse.ss = rss;
4054 gfc_conv_expr (&rse, me);
4057 /* Variable to evaluate mask condition. */
4058 cond = gfc_create_var (mask_type, "cond");
4059 if (mask && (cmask || pmask))
4060 mtmp = gfc_create_var (mask_type, "mask");
4061 else mtmp = NULL_TREE;
4063 gfc_add_block_to_block (&body1, &lse.pre);
4064 gfc_add_block_to_block (&body1, &rse.pre);
4066 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4068 if (mask && (cmask || pmask))
4070 tmp = gfc_build_array_ref (mask, count, NULL);
4071 if (invert)
4072 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4073 gfc_add_modify (&body1, mtmp, tmp);
4076 if (cmask)
4078 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4079 tmp = cond;
4080 if (mask)
4081 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4082 mtmp, tmp);
4083 gfc_add_modify (&body1, tmp1, tmp);
4086 if (pmask)
4088 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4089 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4090 if (mask)
4091 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4092 tmp);
4093 gfc_add_modify (&body1, tmp1, tmp);
4096 gfc_add_block_to_block (&body1, &lse.post);
4097 gfc_add_block_to_block (&body1, &rse.post);
4099 if (lss == gfc_ss_terminator)
4101 gfc_add_block_to_block (&body, &body1);
4103 else
4105 /* Increment count. */
4106 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4107 count, gfc_index_one_node);
4108 gfc_add_modify (&body1, count, tmp1);
4110 /* Generate the copying loops. */
4111 gfc_trans_scalarizing_loops (&loop, &body1);
4113 gfc_add_block_to_block (&body, &loop.pre);
4114 gfc_add_block_to_block (&body, &loop.post);
4116 gfc_cleanup_loop (&loop);
4117 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4118 as tree nodes in SS may not be valid in different scope. */
4121 tmp1 = gfc_finish_block (&body);
4122 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4123 if (nested_forall_info != NULL)
4124 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4126 gfc_add_expr_to_block (block, tmp1);
4130 /* Translate an assignment statement in a WHERE statement or construct
4131 statement. The MASK expression is used to control which elements
4132 of EXPR1 shall be assigned. The sense of MASK is specified by
4133 INVERT. */
4135 static tree
4136 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4137 tree mask, bool invert,
4138 tree count1, tree count2,
4139 gfc_code *cnext)
4141 gfc_se lse;
4142 gfc_se rse;
4143 gfc_ss *lss;
4144 gfc_ss *lss_section;
4145 gfc_ss *rss;
4147 gfc_loopinfo loop;
4148 tree tmp;
4149 stmtblock_t block;
4150 stmtblock_t body;
4151 tree index, maskexpr;
4153 /* A defined assignment. */
4154 if (cnext && cnext->resolved_sym)
4155 return gfc_trans_call (cnext, true, mask, count1, invert);
4157 #if 0
4158 /* TODO: handle this special case.
4159 Special case a single function returning an array. */
4160 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4162 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4163 if (tmp)
4164 return tmp;
4166 #endif
4168 /* Assignment of the form lhs = rhs. */
4169 gfc_start_block (&block);
4171 gfc_init_se (&lse, NULL);
4172 gfc_init_se (&rse, NULL);
4174 /* Walk the lhs. */
4175 lss = gfc_walk_expr (expr1);
4176 rss = NULL;
4178 /* In each where-assign-stmt, the mask-expr and the variable being
4179 defined shall be arrays of the same shape. */
4180 gcc_assert (lss != gfc_ss_terminator);
4182 /* The assignment needs scalarization. */
4183 lss_section = lss;
4185 /* Find a non-scalar SS from the lhs. */
4186 while (lss_section != gfc_ss_terminator
4187 && lss_section->info->type != GFC_SS_SECTION)
4188 lss_section = lss_section->next;
4190 gcc_assert (lss_section != gfc_ss_terminator);
4192 /* Initialize the scalarizer. */
4193 gfc_init_loopinfo (&loop);
4195 /* Walk the rhs. */
4196 rss = gfc_walk_expr (expr2);
4197 if (rss == gfc_ss_terminator)
4199 /* The rhs is scalar. Add a ss for the expression. */
4200 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4201 rss->info->where = 1;
4204 /* Associate the SS with the loop. */
4205 gfc_add_ss_to_loop (&loop, lss);
4206 gfc_add_ss_to_loop (&loop, rss);
4208 /* Calculate the bounds of the scalarization. */
4209 gfc_conv_ss_startstride (&loop);
4211 /* Resolve any data dependencies in the statement. */
4212 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4214 /* Setup the scalarizing loops. */
4215 gfc_conv_loop_setup (&loop, &expr2->where);
4217 /* Setup the gfc_se structures. */
4218 gfc_copy_loopinfo_to_se (&lse, &loop);
4219 gfc_copy_loopinfo_to_se (&rse, &loop);
4221 rse.ss = rss;
4222 gfc_mark_ss_chain_used (rss, 1);
4223 if (loop.temp_ss == NULL)
4225 lse.ss = lss;
4226 gfc_mark_ss_chain_used (lss, 1);
4228 else
4230 lse.ss = loop.temp_ss;
4231 gfc_mark_ss_chain_used (lss, 3);
4232 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4235 /* Start the scalarized loop body. */
4236 gfc_start_scalarized_body (&loop, &body);
4238 /* Translate the expression. */
4239 gfc_conv_expr (&rse, expr2);
4240 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4241 gfc_conv_tmp_array_ref (&lse);
4242 else
4243 gfc_conv_expr (&lse, expr1);
4245 /* Form the mask expression according to the mask. */
4246 index = count1;
4247 maskexpr = gfc_build_array_ref (mask, index, NULL);
4248 if (invert)
4249 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4250 TREE_TYPE (maskexpr), maskexpr);
4252 /* Use the scalar assignment as is. */
4253 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4254 loop.temp_ss != NULL, false, true);
4256 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4258 gfc_add_expr_to_block (&body, tmp);
4260 if (lss == gfc_ss_terminator)
4262 /* Increment count1. */
4263 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4264 count1, gfc_index_one_node);
4265 gfc_add_modify (&body, count1, tmp);
4267 /* Use the scalar assignment as is. */
4268 gfc_add_block_to_block (&block, &body);
4270 else
4272 gcc_assert (lse.ss == gfc_ss_terminator
4273 && rse.ss == gfc_ss_terminator);
4275 if (loop.temp_ss != NULL)
4277 /* Increment count1 before finish the main body of a scalarized
4278 expression. */
4279 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4280 gfc_array_index_type, count1, gfc_index_one_node);
4281 gfc_add_modify (&body, count1, tmp);
4282 gfc_trans_scalarized_loop_boundary (&loop, &body);
4284 /* We need to copy the temporary to the actual lhs. */
4285 gfc_init_se (&lse, NULL);
4286 gfc_init_se (&rse, NULL);
4287 gfc_copy_loopinfo_to_se (&lse, &loop);
4288 gfc_copy_loopinfo_to_se (&rse, &loop);
4290 rse.ss = loop.temp_ss;
4291 lse.ss = lss;
4293 gfc_conv_tmp_array_ref (&rse);
4294 gfc_conv_expr (&lse, expr1);
4296 gcc_assert (lse.ss == gfc_ss_terminator
4297 && rse.ss == gfc_ss_terminator);
4299 /* Form the mask expression according to the mask tree list. */
4300 index = count2;
4301 maskexpr = gfc_build_array_ref (mask, index, NULL);
4302 if (invert)
4303 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4304 TREE_TYPE (maskexpr), maskexpr);
4306 /* Use the scalar assignment as is. */
4307 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4308 true);
4309 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4310 build_empty_stmt (input_location));
4311 gfc_add_expr_to_block (&body, tmp);
4313 /* Increment count2. */
4314 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4315 gfc_array_index_type, count2,
4316 gfc_index_one_node);
4317 gfc_add_modify (&body, count2, tmp);
4319 else
4321 /* Increment count1. */
4322 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4323 gfc_array_index_type, count1,
4324 gfc_index_one_node);
4325 gfc_add_modify (&body, count1, tmp);
4328 /* Generate the copying loops. */
4329 gfc_trans_scalarizing_loops (&loop, &body);
4331 /* Wrap the whole thing up. */
4332 gfc_add_block_to_block (&block, &loop.pre);
4333 gfc_add_block_to_block (&block, &loop.post);
4334 gfc_cleanup_loop (&loop);
4337 return gfc_finish_block (&block);
4341 /* Translate the WHERE construct or statement.
4342 This function can be called iteratively to translate the nested WHERE
4343 construct or statement.
4344 MASK is the control mask. */
4346 static void
4347 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4348 forall_info * nested_forall_info, stmtblock_t * block)
4350 stmtblock_t inner_size_body;
4351 tree inner_size, size;
4352 gfc_ss *lss, *rss;
4353 tree mask_type;
4354 gfc_expr *expr1;
4355 gfc_expr *expr2;
4356 gfc_code *cblock;
4357 gfc_code *cnext;
4358 tree tmp;
4359 tree cond;
4360 tree count1, count2;
4361 bool need_cmask;
4362 bool need_pmask;
4363 int need_temp;
4364 tree pcmask = NULL_TREE;
4365 tree ppmask = NULL_TREE;
4366 tree cmask = NULL_TREE;
4367 tree pmask = NULL_TREE;
4368 gfc_actual_arglist *arg;
4370 /* the WHERE statement or the WHERE construct statement. */
4371 cblock = code->block;
4373 /* As the mask array can be very big, prefer compact boolean types. */
4374 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4376 /* Determine which temporary masks are needed. */
4377 if (!cblock->block)
4379 /* One clause: No ELSEWHEREs. */
4380 need_cmask = (cblock->next != 0);
4381 need_pmask = false;
4383 else if (cblock->block->block)
4385 /* Three or more clauses: Conditional ELSEWHEREs. */
4386 need_cmask = true;
4387 need_pmask = true;
4389 else if (cblock->next)
4391 /* Two clauses, the first non-empty. */
4392 need_cmask = true;
4393 need_pmask = (mask != NULL_TREE
4394 && cblock->block->next != 0);
4396 else if (!cblock->block->next)
4398 /* Two clauses, both empty. */
4399 need_cmask = false;
4400 need_pmask = false;
4402 /* Two clauses, the first empty, the second non-empty. */
4403 else if (mask)
4405 need_cmask = (cblock->block->expr1 != 0);
4406 need_pmask = true;
4408 else
4410 need_cmask = true;
4411 need_pmask = false;
4414 if (need_cmask || need_pmask)
4416 /* Calculate the size of temporary needed by the mask-expr. */
4417 gfc_init_block (&inner_size_body);
4418 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4419 &inner_size_body, &lss, &rss);
4421 gfc_free_ss_chain (lss);
4422 gfc_free_ss_chain (rss);
4424 /* Calculate the total size of temporary needed. */
4425 size = compute_overall_iter_number (nested_forall_info, inner_size,
4426 &inner_size_body, block);
4428 /* Check whether the size is negative. */
4429 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4430 gfc_index_zero_node);
4431 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4432 cond, gfc_index_zero_node, size);
4433 size = gfc_evaluate_now (size, block);
4435 /* Allocate temporary for WHERE mask if needed. */
4436 if (need_cmask)
4437 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4438 &pcmask);
4440 /* Allocate temporary for !mask if needed. */
4441 if (need_pmask)
4442 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4443 &ppmask);
4446 while (cblock)
4448 /* Each time around this loop, the where clause is conditional
4449 on the value of mask and invert, which are updated at the
4450 bottom of the loop. */
4452 /* Has mask-expr. */
4453 if (cblock->expr1)
4455 /* Ensure that the WHERE mask will be evaluated exactly once.
4456 If there are no statements in this WHERE/ELSEWHERE clause,
4457 then we don't need to update the control mask (cmask).
4458 If this is the last clause of the WHERE construct, then
4459 we don't need to update the pending control mask (pmask). */
4460 if (mask)
4461 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4462 mask, invert,
4463 cblock->next ? cmask : NULL_TREE,
4464 cblock->block ? pmask : NULL_TREE,
4465 mask_type, block);
4466 else
4467 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4468 NULL_TREE, false,
4469 (cblock->next || cblock->block)
4470 ? cmask : NULL_TREE,
4471 NULL_TREE, mask_type, block);
4473 invert = false;
4475 /* It's a final elsewhere-stmt. No mask-expr is present. */
4476 else
4477 cmask = mask;
4479 /* The body of this where clause are controlled by cmask with
4480 sense specified by invert. */
4482 /* Get the assignment statement of a WHERE statement, or the first
4483 statement in where-body-construct of a WHERE construct. */
4484 cnext = cblock->next;
4485 while (cnext)
4487 switch (cnext->op)
4489 /* WHERE assignment statement. */
4490 case EXEC_ASSIGN_CALL:
4492 arg = cnext->ext.actual;
4493 expr1 = expr2 = NULL;
4494 for (; arg; arg = arg->next)
4496 if (!arg->expr)
4497 continue;
4498 if (expr1 == NULL)
4499 expr1 = arg->expr;
4500 else
4501 expr2 = arg->expr;
4503 goto evaluate;
4505 case EXEC_ASSIGN:
4506 expr1 = cnext->expr1;
4507 expr2 = cnext->expr2;
4508 evaluate:
4509 if (nested_forall_info != NULL)
4511 need_temp = gfc_check_dependency (expr1, expr2, 0);
4512 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4513 gfc_trans_assign_need_temp (expr1, expr2,
4514 cmask, invert,
4515 nested_forall_info, block);
4516 else
4518 /* Variables to control maskexpr. */
4519 count1 = gfc_create_var (gfc_array_index_type, "count1");
4520 count2 = gfc_create_var (gfc_array_index_type, "count2");
4521 gfc_add_modify (block, count1, gfc_index_zero_node);
4522 gfc_add_modify (block, count2, gfc_index_zero_node);
4524 tmp = gfc_trans_where_assign (expr1, expr2,
4525 cmask, invert,
4526 count1, count2,
4527 cnext);
4529 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4530 tmp, 1);
4531 gfc_add_expr_to_block (block, tmp);
4534 else
4536 /* Variables to control maskexpr. */
4537 count1 = gfc_create_var (gfc_array_index_type, "count1");
4538 count2 = gfc_create_var (gfc_array_index_type, "count2");
4539 gfc_add_modify (block, count1, gfc_index_zero_node);
4540 gfc_add_modify (block, count2, gfc_index_zero_node);
4542 tmp = gfc_trans_where_assign (expr1, expr2,
4543 cmask, invert,
4544 count1, count2,
4545 cnext);
4546 gfc_add_expr_to_block (block, tmp);
4549 break;
4551 /* WHERE or WHERE construct is part of a where-body-construct. */
4552 case EXEC_WHERE:
4553 gfc_trans_where_2 (cnext, cmask, invert,
4554 nested_forall_info, block);
4555 break;
4557 default:
4558 gcc_unreachable ();
4561 /* The next statement within the same where-body-construct. */
4562 cnext = cnext->next;
4564 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4565 cblock = cblock->block;
4566 if (mask == NULL_TREE)
4568 /* If we're the initial WHERE, we can simply invert the sense
4569 of the current mask to obtain the "mask" for the remaining
4570 ELSEWHEREs. */
4571 invert = true;
4572 mask = cmask;
4574 else
4576 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4577 invert = false;
4578 mask = pmask;
4582 /* If we allocated a pending mask array, deallocate it now. */
4583 if (ppmask)
4585 tmp = gfc_call_free (ppmask);
4586 gfc_add_expr_to_block (block, tmp);
4589 /* If we allocated a current mask array, deallocate it now. */
4590 if (pcmask)
4592 tmp = gfc_call_free (pcmask);
4593 gfc_add_expr_to_block (block, tmp);
4597 /* Translate a simple WHERE construct or statement without dependencies.
4598 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4599 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4600 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4602 static tree
4603 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4605 stmtblock_t block, body;
4606 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4607 tree tmp, cexpr, tstmt, estmt;
4608 gfc_ss *css, *tdss, *tsss;
4609 gfc_se cse, tdse, tsse, edse, esse;
4610 gfc_loopinfo loop;
4611 gfc_ss *edss = 0;
4612 gfc_ss *esss = 0;
4614 /* Allow the scalarizer to workshare simple where loops. */
4615 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4616 ompws_flags |= OMPWS_SCALARIZER_WS;
4618 cond = cblock->expr1;
4619 tdst = cblock->next->expr1;
4620 tsrc = cblock->next->expr2;
4621 edst = eblock ? eblock->next->expr1 : NULL;
4622 esrc = eblock ? eblock->next->expr2 : NULL;
4624 gfc_start_block (&block);
4625 gfc_init_loopinfo (&loop);
4627 /* Handle the condition. */
4628 gfc_init_se (&cse, NULL);
4629 css = gfc_walk_expr (cond);
4630 gfc_add_ss_to_loop (&loop, css);
4632 /* Handle the then-clause. */
4633 gfc_init_se (&tdse, NULL);
4634 gfc_init_se (&tsse, NULL);
4635 tdss = gfc_walk_expr (tdst);
4636 tsss = gfc_walk_expr (tsrc);
4637 if (tsss == gfc_ss_terminator)
4639 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4640 tsss->info->where = 1;
4642 gfc_add_ss_to_loop (&loop, tdss);
4643 gfc_add_ss_to_loop (&loop, tsss);
4645 if (eblock)
4647 /* Handle the else clause. */
4648 gfc_init_se (&edse, NULL);
4649 gfc_init_se (&esse, NULL);
4650 edss = gfc_walk_expr (edst);
4651 esss = gfc_walk_expr (esrc);
4652 if (esss == gfc_ss_terminator)
4654 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4655 esss->info->where = 1;
4657 gfc_add_ss_to_loop (&loop, edss);
4658 gfc_add_ss_to_loop (&loop, esss);
4661 gfc_conv_ss_startstride (&loop);
4662 gfc_conv_loop_setup (&loop, &tdst->where);
4664 gfc_mark_ss_chain_used (css, 1);
4665 gfc_mark_ss_chain_used (tdss, 1);
4666 gfc_mark_ss_chain_used (tsss, 1);
4667 if (eblock)
4669 gfc_mark_ss_chain_used (edss, 1);
4670 gfc_mark_ss_chain_used (esss, 1);
4673 gfc_start_scalarized_body (&loop, &body);
4675 gfc_copy_loopinfo_to_se (&cse, &loop);
4676 gfc_copy_loopinfo_to_se (&tdse, &loop);
4677 gfc_copy_loopinfo_to_se (&tsse, &loop);
4678 cse.ss = css;
4679 tdse.ss = tdss;
4680 tsse.ss = tsss;
4681 if (eblock)
4683 gfc_copy_loopinfo_to_se (&edse, &loop);
4684 gfc_copy_loopinfo_to_se (&esse, &loop);
4685 edse.ss = edss;
4686 esse.ss = esss;
4689 gfc_conv_expr (&cse, cond);
4690 gfc_add_block_to_block (&body, &cse.pre);
4691 cexpr = cse.expr;
4693 gfc_conv_expr (&tsse, tsrc);
4694 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4695 gfc_conv_tmp_array_ref (&tdse);
4696 else
4697 gfc_conv_expr (&tdse, tdst);
4699 if (eblock)
4701 gfc_conv_expr (&esse, esrc);
4702 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4703 gfc_conv_tmp_array_ref (&edse);
4704 else
4705 gfc_conv_expr (&edse, edst);
4708 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4709 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4710 false, true)
4711 : build_empty_stmt (input_location);
4712 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4713 gfc_add_expr_to_block (&body, tmp);
4714 gfc_add_block_to_block (&body, &cse.post);
4716 gfc_trans_scalarizing_loops (&loop, &body);
4717 gfc_add_block_to_block (&block, &loop.pre);
4718 gfc_add_block_to_block (&block, &loop.post);
4719 gfc_cleanup_loop (&loop);
4721 return gfc_finish_block (&block);
4724 /* As the WHERE or WHERE construct statement can be nested, we call
4725 gfc_trans_where_2 to do the translation, and pass the initial
4726 NULL values for both the control mask and the pending control mask. */
4728 tree
4729 gfc_trans_where (gfc_code * code)
4731 stmtblock_t block;
4732 gfc_code *cblock;
4733 gfc_code *eblock;
4735 cblock = code->block;
4736 if (cblock->next
4737 && cblock->next->op == EXEC_ASSIGN
4738 && !cblock->next->next)
4740 eblock = cblock->block;
4741 if (!eblock)
4743 /* A simple "WHERE (cond) x = y" statement or block is
4744 dependence free if cond is not dependent upon writing x,
4745 and the source y is unaffected by the destination x. */
4746 if (!gfc_check_dependency (cblock->next->expr1,
4747 cblock->expr1, 0)
4748 && !gfc_check_dependency (cblock->next->expr1,
4749 cblock->next->expr2, 0))
4750 return gfc_trans_where_3 (cblock, NULL);
4752 else if (!eblock->expr1
4753 && !eblock->block
4754 && eblock->next
4755 && eblock->next->op == EXEC_ASSIGN
4756 && !eblock->next->next)
4758 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4759 block is dependence free if cond is not dependent on writes
4760 to x1 and x2, y1 is not dependent on writes to x2, and y2
4761 is not dependent on writes to x1, and both y's are not
4762 dependent upon their own x's. In addition to this, the
4763 final two dependency checks below exclude all but the same
4764 array reference if the where and elswhere destinations
4765 are the same. In short, this is VERY conservative and this
4766 is needed because the two loops, required by the standard
4767 are coalesced in gfc_trans_where_3. */
4768 if (!gfc_check_dependency (cblock->next->expr1,
4769 cblock->expr1, 0)
4770 && !gfc_check_dependency (eblock->next->expr1,
4771 cblock->expr1, 0)
4772 && !gfc_check_dependency (cblock->next->expr1,
4773 eblock->next->expr2, 1)
4774 && !gfc_check_dependency (eblock->next->expr1,
4775 cblock->next->expr2, 1)
4776 && !gfc_check_dependency (cblock->next->expr1,
4777 cblock->next->expr2, 1)
4778 && !gfc_check_dependency (eblock->next->expr1,
4779 eblock->next->expr2, 1)
4780 && !gfc_check_dependency (cblock->next->expr1,
4781 eblock->next->expr1, 0)
4782 && !gfc_check_dependency (eblock->next->expr1,
4783 cblock->next->expr1, 0))
4784 return gfc_trans_where_3 (cblock, eblock);
4788 gfc_start_block (&block);
4790 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4792 return gfc_finish_block (&block);
4796 /* CYCLE a DO loop. The label decl has already been created by
4797 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4798 node at the head of the loop. We must mark the label as used. */
4800 tree
4801 gfc_trans_cycle (gfc_code * code)
4803 tree cycle_label;
4805 cycle_label = code->ext.which_construct->cycle_label;
4806 gcc_assert (cycle_label);
4808 TREE_USED (cycle_label) = 1;
4809 return build1_v (GOTO_EXPR, cycle_label);
4813 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4814 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4815 loop. */
4817 tree
4818 gfc_trans_exit (gfc_code * code)
4820 tree exit_label;
4822 exit_label = code->ext.which_construct->exit_label;
4823 gcc_assert (exit_label);
4825 TREE_USED (exit_label) = 1;
4826 return build1_v (GOTO_EXPR, exit_label);
4830 /* Translate the ALLOCATE statement. */
4832 tree
4833 gfc_trans_allocate (gfc_code * code)
4835 gfc_alloc *al;
4836 gfc_expr *e;
4837 gfc_expr *expr;
4838 gfc_se se;
4839 tree tmp;
4840 tree parm;
4841 tree stat;
4842 tree errmsg;
4843 tree errlen;
4844 tree label_errmsg;
4845 tree label_finish;
4846 tree memsz;
4847 tree expr3;
4848 tree slen3;
4849 stmtblock_t block;
4850 stmtblock_t post;
4851 gfc_expr *sz;
4852 gfc_se se_sz;
4853 tree class_expr;
4854 tree nelems;
4855 tree memsize = NULL_TREE;
4856 tree classexpr = NULL_TREE;
4858 if (!code->ext.alloc.list)
4859 return NULL_TREE;
4861 stat = tmp = memsz = NULL_TREE;
4862 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4864 gfc_init_block (&block);
4865 gfc_init_block (&post);
4867 /* STAT= (and maybe ERRMSG=) is present. */
4868 if (code->expr1)
4870 /* STAT=. */
4871 tree gfc_int4_type_node = gfc_get_int_type (4);
4872 stat = gfc_create_var (gfc_int4_type_node, "stat");
4874 /* ERRMSG= only makes sense with STAT=. */
4875 if (code->expr2)
4877 gfc_init_se (&se, NULL);
4878 se.want_pointer = 1;
4879 gfc_conv_expr_lhs (&se, code->expr2);
4880 errmsg = se.expr;
4881 errlen = se.string_length;
4883 else
4885 errmsg = null_pointer_node;
4886 errlen = build_int_cst (gfc_charlen_type_node, 0);
4889 /* GOTO destinations. */
4890 label_errmsg = gfc_build_label_decl (NULL_TREE);
4891 label_finish = gfc_build_label_decl (NULL_TREE);
4892 TREE_USED (label_finish) = 0;
4895 expr3 = NULL_TREE;
4896 slen3 = NULL_TREE;
4898 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4900 expr = gfc_copy_expr (al->expr);
4902 if (expr->ts.type == BT_CLASS)
4903 gfc_add_data_component (expr);
4905 gfc_init_se (&se, NULL);
4907 se.want_pointer = 1;
4908 se.descriptor_only = 1;
4909 gfc_conv_expr (&se, expr);
4911 /* Evaluate expr3 just once if not a variable. */
4912 if (al == code->ext.alloc.list
4913 && al->expr->ts.type == BT_CLASS
4914 && code->expr3
4915 && code->expr3->ts.type == BT_CLASS
4916 && code->expr3->expr_type != EXPR_VARIABLE)
4918 gfc_init_se (&se_sz, NULL);
4919 gfc_conv_expr_reference (&se_sz, code->expr3);
4920 gfc_conv_class_to_class (&se_sz, code->expr3,
4921 code->expr3->ts, false, true, false, false);
4922 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4923 gfc_add_block_to_block (&se.post, &se_sz.post);
4924 classexpr = build_fold_indirect_ref_loc (input_location,
4925 se_sz.expr);
4926 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4927 memsize = gfc_vtable_size_get (classexpr);
4928 memsize = fold_convert (sizetype, memsize);
4931 memsz = memsize;
4932 class_expr = classexpr;
4934 nelems = NULL_TREE;
4935 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4936 memsz, &nelems, code->expr3, &code->ext.alloc.ts))
4938 bool unlimited_char;
4940 unlimited_char = UNLIMITED_POLY (al->expr)
4941 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
4942 || (code->ext.alloc.ts.type == BT_CHARACTER
4943 && code->ext.alloc.ts.u.cl
4944 && code->ext.alloc.ts.u.cl->length));
4946 /* A scalar or derived type. */
4948 /* Determine allocate size. */
4949 if (al->expr->ts.type == BT_CLASS
4950 && !unlimited_char
4951 && code->expr3
4952 && memsz == NULL_TREE)
4954 if (code->expr3->ts.type == BT_CLASS)
4956 sz = gfc_copy_expr (code->expr3);
4957 gfc_add_vptr_component (sz);
4958 gfc_add_size_component (sz);
4959 gfc_init_se (&se_sz, NULL);
4960 gfc_conv_expr (&se_sz, sz);
4961 gfc_free_expr (sz);
4962 memsz = se_sz.expr;
4964 else
4965 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
4967 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4968 || unlimited_char) && code->expr3)
4970 if (!code->expr3->ts.u.cl->backend_decl)
4972 /* Convert and use the length expression. */
4973 gfc_init_se (&se_sz, NULL);
4974 if (code->expr3->expr_type == EXPR_VARIABLE
4975 || code->expr3->expr_type == EXPR_CONSTANT)
4977 gfc_conv_expr (&se_sz, code->expr3);
4978 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4979 se_sz.string_length
4980 = gfc_evaluate_now (se_sz.string_length, &se.pre);
4981 gfc_add_block_to_block (&se.pre, &se_sz.post);
4982 memsz = se_sz.string_length;
4984 else if (code->expr3->mold
4985 && code->expr3->ts.u.cl
4986 && code->expr3->ts.u.cl->length)
4988 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
4989 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4990 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4991 gfc_add_block_to_block (&se.pre, &se_sz.post);
4992 memsz = se_sz.expr;
4994 else
4996 /* This is would be inefficient and possibly could
4997 generate wrong code if the result were not stored
4998 in expr3/slen3. */
4999 if (slen3 == NULL_TREE)
5001 gfc_conv_expr (&se_sz, code->expr3);
5002 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5003 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
5004 gfc_add_block_to_block (&post, &se_sz.post);
5005 slen3 = gfc_evaluate_now (se_sz.string_length,
5006 &se.pre);
5008 memsz = slen3;
5011 else
5012 /* Otherwise use the stored string length. */
5013 memsz = code->expr3->ts.u.cl->backend_decl;
5014 tmp = al->expr->ts.u.cl->backend_decl;
5016 /* Store the string length. */
5017 if (tmp && TREE_CODE (tmp) == VAR_DECL)
5018 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5019 memsz));
5021 /* Convert to size in bytes, using the character KIND. */
5022 if (unlimited_char)
5023 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5024 else
5025 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5026 tmp = TYPE_SIZE_UNIT (tmp);
5027 memsz = fold_build2_loc (input_location, MULT_EXPR,
5028 TREE_TYPE (tmp), tmp,
5029 fold_convert (TREE_TYPE (tmp), memsz));
5031 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5032 || unlimited_char)
5034 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5035 gfc_init_se (&se_sz, NULL);
5036 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5037 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5038 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5039 gfc_add_block_to_block (&se.pre, &se_sz.post);
5040 /* Store the string length. */
5041 tmp = al->expr->ts.u.cl->backend_decl;
5042 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5043 se_sz.expr));
5044 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5045 tmp = TYPE_SIZE_UNIT (tmp);
5046 memsz = fold_build2_loc (input_location, MULT_EXPR,
5047 TREE_TYPE (tmp), tmp,
5048 fold_convert (TREE_TYPE (se_sz.expr),
5049 se_sz.expr));
5051 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5052 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5053 else if (memsz == NULL_TREE)
5054 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5056 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5058 memsz = se.string_length;
5060 /* Convert to size in bytes, using the character KIND. */
5061 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5062 tmp = TYPE_SIZE_UNIT (tmp);
5063 memsz = fold_build2_loc (input_location, MULT_EXPR,
5064 TREE_TYPE (tmp), tmp,
5065 fold_convert (TREE_TYPE (tmp), memsz));
5068 /* Allocate - for non-pointers with re-alloc checking. */
5069 if (gfc_expr_attr (expr).allocatable)
5070 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5071 stat, errmsg, errlen, label_finish, expr);
5072 else
5073 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5075 if (al->expr->ts.type == BT_DERIVED
5076 && expr->ts.u.derived->attr.alloc_comp)
5078 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5079 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5080 gfc_add_expr_to_block (&se.pre, tmp);
5084 gfc_add_block_to_block (&block, &se.pre);
5086 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5087 if (code->expr1)
5089 tmp = build1_v (GOTO_EXPR, label_errmsg);
5090 parm = fold_build2_loc (input_location, NE_EXPR,
5091 boolean_type_node, stat,
5092 build_int_cst (TREE_TYPE (stat), 0));
5093 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5094 gfc_unlikely (parm), tmp,
5095 build_empty_stmt (input_location));
5096 gfc_add_expr_to_block (&block, tmp);
5099 /* We need the vptr of CLASS objects to be initialized. */
5100 e = gfc_copy_expr (al->expr);
5101 if (e->ts.type == BT_CLASS)
5103 gfc_expr *lhs, *rhs;
5104 gfc_se lse;
5106 lhs = gfc_expr_to_initialize (e);
5107 gfc_add_vptr_component (lhs);
5109 if (class_expr != NULL_TREE)
5111 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5112 gfc_init_se (&lse, NULL);
5113 lse.want_pointer = 1;
5114 gfc_conv_expr (&lse, lhs);
5115 tmp = gfc_class_vptr_get (class_expr);
5116 gfc_add_modify (&block, lse.expr,
5117 fold_convert (TREE_TYPE (lse.expr), tmp));
5119 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5121 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5122 rhs = gfc_copy_expr (code->expr3);
5123 gfc_add_vptr_component (rhs);
5124 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5125 gfc_add_expr_to_block (&block, tmp);
5126 gfc_free_expr (rhs);
5127 rhs = gfc_expr_to_initialize (e);
5129 else
5131 /* VPTR is fixed at compile time. */
5132 gfc_symbol *vtab;
5133 gfc_typespec *ts;
5134 if (code->expr3)
5135 ts = &code->expr3->ts;
5136 else if (e->ts.type == BT_DERIVED)
5137 ts = &e->ts;
5138 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
5139 ts = &code->ext.alloc.ts;
5140 else if (e->ts.type == BT_CLASS)
5141 ts = &CLASS_DATA (e)->ts;
5142 else
5143 ts = &e->ts;
5145 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
5147 if (ts->type == BT_DERIVED)
5148 vtab = gfc_find_derived_vtab (ts->u.derived);
5149 else
5150 vtab = gfc_find_intrinsic_vtab (ts);
5151 gcc_assert (vtab);
5152 gfc_init_se (&lse, NULL);
5153 lse.want_pointer = 1;
5154 gfc_conv_expr (&lse, lhs);
5155 tmp = gfc_build_addr_expr (NULL_TREE,
5156 gfc_get_symbol_decl (vtab));
5157 gfc_add_modify (&block, lse.expr,
5158 fold_convert (TREE_TYPE (lse.expr), tmp));
5161 gfc_free_expr (lhs);
5164 gfc_free_expr (e);
5166 if (code->expr3 && !code->expr3->mold)
5168 /* Initialization via SOURCE block
5169 (or static default initializer). */
5170 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5171 if (class_expr != NULL_TREE)
5173 tree to;
5174 to = TREE_OPERAND (se.expr, 0);
5176 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5178 else if (al->expr->ts.type == BT_CLASS)
5180 gfc_actual_arglist *actual;
5181 gfc_expr *ppc;
5182 gfc_code *ppc_code;
5183 gfc_ref *ref, *dataref;
5185 /* Do a polymorphic deep copy. */
5186 actual = gfc_get_actual_arglist ();
5187 actual->expr = gfc_copy_expr (rhs);
5188 if (rhs->ts.type == BT_CLASS)
5189 gfc_add_data_component (actual->expr);
5190 actual->next = gfc_get_actual_arglist ();
5191 actual->next->expr = gfc_copy_expr (al->expr);
5192 actual->next->expr->ts.type = BT_CLASS;
5193 gfc_add_data_component (actual->next->expr);
5195 dataref = NULL;
5196 /* Make sure we go up through the reference chain to
5197 the _data reference, where the arrayspec is found. */
5198 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5199 if (ref->type == REF_COMPONENT
5200 && strcmp (ref->u.c.component->name, "_data") == 0)
5201 dataref = ref;
5203 if (dataref && dataref->u.c.component->as)
5205 int dim;
5206 gfc_expr *temp;
5207 gfc_ref *ref = dataref->next;
5208 ref->u.ar.type = AR_SECTION;
5209 /* We have to set up the array reference to give ranges
5210 in all dimensions and ensure that the end and stride
5211 are set so that the copy can be scalarized. */
5212 dim = 0;
5213 for (; dim < dataref->u.c.component->as->rank; dim++)
5215 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5216 if (ref->u.ar.end[dim] == NULL)
5218 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5219 temp = gfc_get_int_expr (gfc_default_integer_kind,
5220 &al->expr->where, 1);
5221 ref->u.ar.start[dim] = temp;
5223 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5224 gfc_copy_expr (ref->u.ar.start[dim]));
5225 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5226 &al->expr->where, 1),
5227 temp);
5230 if (rhs->ts.type == BT_CLASS)
5232 ppc = gfc_copy_expr (rhs);
5233 gfc_add_vptr_component (ppc);
5235 else if (rhs->ts.type == BT_DERIVED)
5236 ppc = gfc_lval_expr_from_sym
5237 (gfc_find_derived_vtab (rhs->ts.u.derived));
5238 else
5239 ppc = gfc_lval_expr_from_sym
5240 (gfc_find_intrinsic_vtab (&rhs->ts));
5241 gfc_add_component_ref (ppc, "_copy");
5243 ppc_code = gfc_get_code (EXEC_CALL);
5244 ppc_code->resolved_sym = ppc->symtree->n.sym;
5245 /* Although '_copy' is set to be elemental in class.c, it is
5246 not staying that way. Find out why, sometime.... */
5247 ppc_code->resolved_sym->attr.elemental = 1;
5248 ppc_code->ext.actual = actual;
5249 ppc_code->expr1 = ppc;
5250 /* Since '_copy' is elemental, the scalarizer will take care
5251 of arrays in gfc_trans_call. */
5252 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5253 gfc_free_statements (ppc_code);
5255 else if (expr3 != NULL_TREE)
5257 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5258 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5259 slen3, expr3, code->expr3->ts.kind);
5260 tmp = NULL_TREE;
5262 else
5264 /* Switch off automatic reallocation since we have just done
5265 the ALLOCATE. */
5266 int realloc_lhs = gfc_option.flag_realloc_lhs;
5267 gfc_option.flag_realloc_lhs = 0;
5268 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5269 rhs, false, false);
5270 gfc_option.flag_realloc_lhs = realloc_lhs;
5272 gfc_free_expr (rhs);
5273 gfc_add_expr_to_block (&block, tmp);
5275 else if (code->expr3 && code->expr3->mold
5276 && code->expr3->ts.type == BT_CLASS)
5278 /* Since the _vptr has already been assigned to the allocate
5279 object, we can use gfc_copy_class_to_class in its
5280 initialization mode. */
5281 tmp = TREE_OPERAND (se.expr, 0);
5282 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5283 gfc_add_expr_to_block (&block, tmp);
5286 gfc_free_expr (expr);
5289 /* STAT. */
5290 if (code->expr1)
5292 tmp = build1_v (LABEL_EXPR, label_errmsg);
5293 gfc_add_expr_to_block (&block, tmp);
5296 /* ERRMSG - only useful if STAT is present. */
5297 if (code->expr1 && code->expr2)
5299 const char *msg = "Attempt to allocate an allocated object";
5300 tree slen, dlen, errmsg_str;
5301 stmtblock_t errmsg_block;
5303 gfc_init_block (&errmsg_block);
5305 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5306 gfc_add_modify (&errmsg_block, errmsg_str,
5307 gfc_build_addr_expr (pchar_type_node,
5308 gfc_build_localized_cstring_const (msg)));
5310 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5311 dlen = gfc_get_expr_charlen (code->expr2);
5312 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5313 slen);
5315 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5316 slen, errmsg_str, gfc_default_character_kind);
5317 dlen = gfc_finish_block (&errmsg_block);
5319 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5320 build_int_cst (TREE_TYPE (stat), 0));
5322 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5324 gfc_add_expr_to_block (&block, tmp);
5327 /* STAT block. */
5328 if (code->expr1)
5330 if (TREE_USED (label_finish))
5332 tmp = build1_v (LABEL_EXPR, label_finish);
5333 gfc_add_expr_to_block (&block, tmp);
5336 gfc_init_se (&se, NULL);
5337 gfc_conv_expr_lhs (&se, code->expr1);
5338 tmp = convert (TREE_TYPE (se.expr), stat);
5339 gfc_add_modify (&block, se.expr, tmp);
5342 gfc_add_block_to_block (&block, &se.post);
5343 gfc_add_block_to_block (&block, &post);
5345 return gfc_finish_block (&block);
5349 /* Translate a DEALLOCATE statement. */
5351 tree
5352 gfc_trans_deallocate (gfc_code *code)
5354 gfc_se se;
5355 gfc_alloc *al;
5356 tree apstat, pstat, stat, errmsg, errlen, tmp;
5357 tree label_finish, label_errmsg;
5358 stmtblock_t block;
5360 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5361 label_finish = label_errmsg = NULL_TREE;
5363 gfc_start_block (&block);
5365 /* Count the number of failed deallocations. If deallocate() was
5366 called with STAT= , then set STAT to the count. If deallocate
5367 was called with ERRMSG, then set ERRMG to a string. */
5368 if (code->expr1)
5370 tree gfc_int4_type_node = gfc_get_int_type (4);
5372 stat = gfc_create_var (gfc_int4_type_node, "stat");
5373 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5375 /* GOTO destinations. */
5376 label_errmsg = gfc_build_label_decl (NULL_TREE);
5377 label_finish = gfc_build_label_decl (NULL_TREE);
5378 TREE_USED (label_finish) = 0;
5381 /* Set ERRMSG - only needed if STAT is available. */
5382 if (code->expr1 && code->expr2)
5384 gfc_init_se (&se, NULL);
5385 se.want_pointer = 1;
5386 gfc_conv_expr_lhs (&se, code->expr2);
5387 errmsg = se.expr;
5388 errlen = se.string_length;
5391 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5393 gfc_expr *expr = gfc_copy_expr (al->expr);
5394 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5396 if (expr->ts.type == BT_CLASS)
5397 gfc_add_data_component (expr);
5399 gfc_init_se (&se, NULL);
5400 gfc_start_block (&se.pre);
5402 se.want_pointer = 1;
5403 se.descriptor_only = 1;
5404 gfc_conv_expr (&se, expr);
5406 if (expr->rank || gfc_is_coarray (expr))
5408 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
5409 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5411 gfc_ref *ref;
5412 gfc_ref *last = NULL;
5413 for (ref = expr->ref; ref; ref = ref->next)
5414 if (ref->type == REF_COMPONENT)
5415 last = ref;
5417 /* Do not deallocate the components of a derived type
5418 ultimate pointer component. */
5419 if (!(last && last->u.c.component->attr.pointer)
5420 && !(!last && expr->symtree->n.sym->attr.pointer))
5422 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5423 expr->rank);
5424 gfc_add_expr_to_block (&se.pre, tmp);
5427 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5428 label_finish, expr);
5429 gfc_add_expr_to_block (&se.pre, tmp);
5430 if (al->expr->ts.type == BT_CLASS)
5431 gfc_reset_vptr (&se.pre, al->expr);
5433 else
5435 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5436 al->expr, al->expr->ts);
5437 gfc_add_expr_to_block (&se.pre, tmp);
5439 /* Set to zero after deallocation. */
5440 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5441 se.expr,
5442 build_int_cst (TREE_TYPE (se.expr), 0));
5443 gfc_add_expr_to_block (&se.pre, tmp);
5445 if (al->expr->ts.type == BT_CLASS)
5446 gfc_reset_vptr (&se.pre, al->expr);
5449 if (code->expr1)
5451 tree cond;
5453 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5454 build_int_cst (TREE_TYPE (stat), 0));
5455 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5456 gfc_unlikely (cond),
5457 build1_v (GOTO_EXPR, label_errmsg),
5458 build_empty_stmt (input_location));
5459 gfc_add_expr_to_block (&se.pre, tmp);
5462 tmp = gfc_finish_block (&se.pre);
5463 gfc_add_expr_to_block (&block, tmp);
5464 gfc_free_expr (expr);
5467 if (code->expr1)
5469 tmp = build1_v (LABEL_EXPR, label_errmsg);
5470 gfc_add_expr_to_block (&block, tmp);
5473 /* Set ERRMSG - only needed if STAT is available. */
5474 if (code->expr1 && code->expr2)
5476 const char *msg = "Attempt to deallocate an unallocated object";
5477 stmtblock_t errmsg_block;
5478 tree errmsg_str, slen, dlen, cond;
5480 gfc_init_block (&errmsg_block);
5482 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5483 gfc_add_modify (&errmsg_block, errmsg_str,
5484 gfc_build_addr_expr (pchar_type_node,
5485 gfc_build_localized_cstring_const (msg)));
5486 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5487 dlen = gfc_get_expr_charlen (code->expr2);
5489 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5490 slen, errmsg_str, gfc_default_character_kind);
5491 tmp = gfc_finish_block (&errmsg_block);
5493 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5494 build_int_cst (TREE_TYPE (stat), 0));
5495 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5496 gfc_unlikely (cond), tmp,
5497 build_empty_stmt (input_location));
5499 gfc_add_expr_to_block (&block, tmp);
5502 if (code->expr1 && TREE_USED (label_finish))
5504 tmp = build1_v (LABEL_EXPR, label_finish);
5505 gfc_add_expr_to_block (&block, tmp);
5508 /* Set STAT. */
5509 if (code->expr1)
5511 gfc_init_se (&se, NULL);
5512 gfc_conv_expr_lhs (&se, code->expr1);
5513 tmp = convert (TREE_TYPE (se.expr), stat);
5514 gfc_add_modify (&block, se.expr, tmp);
5517 return gfc_finish_block (&block);
5520 #include "gt-fortran-trans-stmt.h"