make __stl_prime_list in comdat
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob0d793f96858c71bc176fecef5bc1c63198bb8107
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011
4 Free Software Foundation, Inc.
5 Contributed by Paul Brook <paul@nowt.org>
6 and Steven Bosscher <s.bosscher@student.tudelft.nl>
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tree.h"
29 #include "gfortran.h"
30 #include "flags.h"
31 #include "trans.h"
32 #include "trans-stmt.h"
33 #include "trans-types.h"
34 #include "trans-array.h"
35 #include "trans-const.h"
36 #include "arith.h"
37 #include "dependency.h"
38 #include "ggc.h"
40 typedef struct iter_info
42 tree var;
43 tree start;
44 tree end;
45 tree step;
46 struct iter_info *next;
48 iter_info;
50 typedef struct forall_info
52 iter_info *this_loop;
53 tree mask;
54 tree maskindex;
55 int nvar;
56 tree size;
57 struct forall_info *prev_nest;
59 forall_info;
61 static void gfc_trans_where_2 (gfc_code *, tree, bool,
62 forall_info *, stmtblock_t *);
64 /* Translate a F95 label number to a LABEL_EXPR. */
66 tree
67 gfc_trans_label_here (gfc_code * code)
69 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
73 /* Given a variable expression which has been ASSIGNed to, find the decl
74 containing the auxiliary variables. For variables in common blocks this
75 is a field_decl. */
77 void
78 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
80 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
81 gfc_conv_expr (se, expr);
82 /* Deals with variable in common block. Get the field declaration. */
83 if (TREE_CODE (se->expr) == COMPONENT_REF)
84 se->expr = TREE_OPERAND (se->expr, 1);
85 /* Deals with dummy argument. Get the parameter declaration. */
86 else if (TREE_CODE (se->expr) == INDIRECT_REF)
87 se->expr = TREE_OPERAND (se->expr, 0);
90 /* Translate a label assignment statement. */
92 tree
93 gfc_trans_label_assign (gfc_code * code)
95 tree label_tree;
96 gfc_se se;
97 tree len;
98 tree addr;
99 tree len_tree;
100 int label_len;
102 /* Start a new block. */
103 gfc_init_se (&se, NULL);
104 gfc_start_block (&se.pre);
105 gfc_conv_label_variable (&se, code->expr1);
107 len = GFC_DECL_STRING_LEN (se.expr);
108 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
110 label_tree = gfc_get_label_decl (code->label1);
112 if (code->label1->defined == ST_LABEL_TARGET)
114 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
115 len_tree = integer_minus_one_node;
117 else
119 gfc_expr *format = code->label1->format;
121 label_len = format->value.character.length;
122 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
123 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
124 format->value.character.string);
125 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
128 gfc_add_modify (&se.pre, len, len_tree);
129 gfc_add_modify (&se.pre, addr, label_tree);
131 return gfc_finish_block (&se.pre);
134 /* Translate a GOTO statement. */
136 tree
137 gfc_trans_goto (gfc_code * code)
139 locus loc = code->loc;
140 tree assigned_goto;
141 tree target;
142 tree tmp;
143 gfc_se se;
145 if (code->label1 != NULL)
146 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
148 /* ASSIGNED GOTO. */
149 gfc_init_se (&se, NULL);
150 gfc_start_block (&se.pre);
151 gfc_conv_label_variable (&se, code->expr1);
152 tmp = GFC_DECL_STRING_LEN (se.expr);
153 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
154 build_int_cst (TREE_TYPE (tmp), -1));
155 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
156 "Assigned label is not a target label");
158 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
160 /* We're going to ignore a label list. It does not really change the
161 statement's semantics (because it is just a further restriction on
162 what's legal code); before, we were comparing label addresses here, but
163 that's a very fragile business and may break with optimization. So
164 just ignore it. */
166 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
167 assigned_goto);
168 gfc_add_expr_to_block (&se.pre, target);
169 return gfc_finish_block (&se.pre);
173 /* Translate an ENTRY statement. Just adds a label for this entry point. */
174 tree
175 gfc_trans_entry (gfc_code * code)
177 return build1_v (LABEL_EXPR, code->ext.entry->label);
181 /* Replace a gfc_ss structure by another both in the gfc_se struct
182 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
183 to replace a variable ss by the corresponding temporary. */
185 static void
186 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
188 gfc_ss **sess, **loopss;
190 /* The old_ss is a ss for a single variable. */
191 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
193 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
194 if (*sess == old_ss)
195 break;
196 gcc_assert (*sess != gfc_ss_terminator);
198 *sess = new_ss;
199 new_ss->next = old_ss->next;
202 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
203 loopss = &((*loopss)->loop_chain))
204 if (*loopss == old_ss)
205 break;
206 gcc_assert (*loopss != gfc_ss_terminator);
208 *loopss = new_ss;
209 new_ss->loop_chain = old_ss->loop_chain;
210 new_ss->loop = old_ss->loop;
212 gfc_free_ss (old_ss);
216 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
217 elemental subroutines. Make temporaries for output arguments if any such
218 dependencies are found. Output arguments are chosen because internal_unpack
219 can be used, as is, to copy the result back to the variable. */
220 static void
221 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
222 gfc_symbol * sym, gfc_actual_arglist * arg,
223 gfc_dep_check check_variable)
225 gfc_actual_arglist *arg0;
226 gfc_expr *e;
227 gfc_formal_arglist *formal;
228 gfc_se parmse;
229 gfc_ss *ss;
230 gfc_symbol *fsym;
231 tree data;
232 tree size;
233 tree tmp;
235 if (loopse->ss == NULL)
236 return;
238 ss = loopse->ss;
239 arg0 = arg;
240 formal = sym->formal;
242 /* Loop over all the arguments testing for dependencies. */
243 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
245 e = arg->expr;
246 if (e == NULL)
247 continue;
249 /* Obtain the info structure for the current argument. */
250 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
251 if (ss->info->expr == e)
252 break;
254 /* If there is a dependency, create a temporary and use it
255 instead of the variable. */
256 fsym = formal ? formal->sym : NULL;
257 if (e->expr_type == EXPR_VARIABLE
258 && e->rank && fsym
259 && fsym->attr.intent != INTENT_IN
260 && gfc_check_fncall_dependency (e, fsym->attr.intent,
261 sym, arg0, check_variable))
263 tree initial, temptype;
264 stmtblock_t temp_post;
265 gfc_ss *tmp_ss;
267 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
268 GFC_SS_SECTION);
269 gfc_mark_ss_chain_used (tmp_ss, 1);
270 tmp_ss->info->expr = ss->info->expr;
271 replace_ss (loopse, ss, tmp_ss);
273 /* Obtain the argument descriptor for unpacking. */
274 gfc_init_se (&parmse, NULL);
275 parmse.want_pointer = 1;
276 gfc_conv_expr_descriptor (&parmse, e, gfc_walk_expr (e));
277 gfc_add_block_to_block (&se->pre, &parmse.pre);
279 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
280 initialize the array temporary with a copy of the values. */
281 if (fsym->attr.intent == INTENT_INOUT
282 || (fsym->ts.type ==BT_DERIVED
283 && fsym->attr.intent == INTENT_OUT))
284 initial = parmse.expr;
285 else
286 initial = NULL_TREE;
288 /* Find the type of the temporary to create; we don't use the type
289 of e itself as this breaks for subcomponent-references in e (where
290 the type of e is that of the final reference, but parmse.expr's
291 type corresponds to the full derived-type). */
292 /* TODO: Fix this somehow so we don't need a temporary of the whole
293 array but instead only the components referenced. */
294 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
295 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
296 temptype = TREE_TYPE (temptype);
297 temptype = gfc_get_element_type (temptype);
299 /* Generate the temporary. Cleaning up the temporary should be the
300 very last thing done, so we add the code to a new block and add it
301 to se->post as last instructions. */
302 size = gfc_create_var (gfc_array_index_type, NULL);
303 data = gfc_create_var (pvoid_type_node, NULL);
304 gfc_init_block (&temp_post);
305 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
306 temptype, initial, false, true,
307 false, &arg->expr->where);
308 gfc_add_modify (&se->pre, size, tmp);
309 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
310 gfc_add_modify (&se->pre, data, tmp);
312 /* Update other ss' delta. */
313 gfc_set_delta (loopse->loop);
315 /* Copy the result back using unpack. */
316 tmp = build_call_expr_loc (input_location,
317 gfor_fndecl_in_unpack, 2, parmse.expr, data);
318 gfc_add_expr_to_block (&se->post, tmp);
320 /* parmse.pre is already added above. */
321 gfc_add_block_to_block (&se->post, &parmse.post);
322 gfc_add_block_to_block (&se->post, &temp_post);
328 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
330 tree
331 gfc_trans_call (gfc_code * code, bool dependency_check,
332 tree mask, tree count1, bool invert)
334 gfc_se se;
335 gfc_ss * ss;
336 int has_alternate_specifier;
337 gfc_dep_check check_variable;
338 tree index = NULL_TREE;
339 tree maskexpr = NULL_TREE;
340 tree tmp;
342 /* A CALL starts a new block because the actual arguments may have to
343 be evaluated first. */
344 gfc_init_se (&se, NULL);
345 gfc_start_block (&se.pre);
347 gcc_assert (code->resolved_sym);
349 ss = gfc_ss_terminator;
350 if (code->resolved_sym->attr.elemental)
351 ss = gfc_walk_elemental_function_args (ss, code->ext.actual, GFC_SS_REFERENCE);
353 /* Is not an elemental subroutine call with array valued arguments. */
354 if (ss == gfc_ss_terminator)
357 /* Translate the call. */
358 has_alternate_specifier
359 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
360 code->expr1, NULL);
362 /* A subroutine without side-effect, by definition, does nothing! */
363 TREE_SIDE_EFFECTS (se.expr) = 1;
365 /* Chain the pieces together and return the block. */
366 if (has_alternate_specifier)
368 gfc_code *select_code;
369 gfc_symbol *sym;
370 select_code = code->next;
371 gcc_assert(select_code->op == EXEC_SELECT);
372 sym = select_code->expr1->symtree->n.sym;
373 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
374 if (sym->backend_decl == NULL)
375 sym->backend_decl = gfc_get_symbol_decl (sym);
376 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
378 else
379 gfc_add_expr_to_block (&se.pre, se.expr);
381 gfc_add_block_to_block (&se.pre, &se.post);
384 else
386 /* An elemental subroutine call with array valued arguments has
387 to be scalarized. */
388 gfc_loopinfo loop;
389 stmtblock_t body;
390 stmtblock_t block;
391 gfc_se loopse;
392 gfc_se depse;
394 /* gfc_walk_elemental_function_args renders the ss chain in the
395 reverse order to the actual argument order. */
396 ss = gfc_reverse_ss (ss);
398 /* Initialize the loop. */
399 gfc_init_se (&loopse, NULL);
400 gfc_init_loopinfo (&loop);
401 gfc_add_ss_to_loop (&loop, ss);
403 gfc_conv_ss_startstride (&loop);
404 /* TODO: gfc_conv_loop_setup generates a temporary for vector
405 subscripts. This could be prevented in the elemental case
406 as temporaries are handled separatedly
407 (below in gfc_conv_elemental_dependencies). */
408 gfc_conv_loop_setup (&loop, &code->expr1->where);
409 gfc_mark_ss_chain_used (ss, 1);
411 /* Convert the arguments, checking for dependencies. */
412 gfc_copy_loopinfo_to_se (&loopse, &loop);
413 loopse.ss = ss;
415 /* For operator assignment, do dependency checking. */
416 if (dependency_check)
417 check_variable = ELEM_CHECK_VARIABLE;
418 else
419 check_variable = ELEM_DONT_CHECK_VARIABLE;
421 gfc_init_se (&depse, NULL);
422 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
423 code->ext.actual, check_variable);
425 gfc_add_block_to_block (&loop.pre, &depse.pre);
426 gfc_add_block_to_block (&loop.post, &depse.post);
428 /* Generate the loop body. */
429 gfc_start_scalarized_body (&loop, &body);
430 gfc_init_block (&block);
432 if (mask && count1)
434 /* Form the mask expression according to the mask. */
435 index = count1;
436 maskexpr = gfc_build_array_ref (mask, index, NULL);
437 if (invert)
438 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
439 TREE_TYPE (maskexpr), maskexpr);
442 /* Add the subroutine call to the block. */
443 gfc_conv_procedure_call (&loopse, code->resolved_sym,
444 code->ext.actual, code->expr1, NULL);
446 if (mask && count1)
448 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
449 build_empty_stmt (input_location));
450 gfc_add_expr_to_block (&loopse.pre, tmp);
451 tmp = fold_build2_loc (input_location, PLUS_EXPR,
452 gfc_array_index_type,
453 count1, gfc_index_one_node);
454 gfc_add_modify (&loopse.pre, count1, tmp);
456 else
457 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
459 gfc_add_block_to_block (&block, &loopse.pre);
460 gfc_add_block_to_block (&block, &loopse.post);
462 /* Finish up the loop block and the loop. */
463 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
464 gfc_trans_scalarizing_loops (&loop, &body);
465 gfc_add_block_to_block (&se.pre, &loop.pre);
466 gfc_add_block_to_block (&se.pre, &loop.post);
467 gfc_add_block_to_block (&se.pre, &se.post);
468 gfc_cleanup_loop (&loop);
471 return gfc_finish_block (&se.pre);
475 /* Translate the RETURN statement. */
477 tree
478 gfc_trans_return (gfc_code * code)
480 if (code->expr1)
482 gfc_se se;
483 tree tmp;
484 tree result;
486 /* If code->expr is not NULL, this return statement must appear
487 in a subroutine and current_fake_result_decl has already
488 been generated. */
490 result = gfc_get_fake_result_decl (NULL, 0);
491 if (!result)
493 gfc_warning ("An alternate return at %L without a * dummy argument",
494 &code->expr1->where);
495 return gfc_generate_return ();
498 /* Start a new block for this statement. */
499 gfc_init_se (&se, NULL);
500 gfc_start_block (&se.pre);
502 gfc_conv_expr (&se, code->expr1);
504 /* Note that the actually returned expression is a simple value and
505 does not depend on any pointers or such; thus we can clean-up with
506 se.post before returning. */
507 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
508 result, fold_convert (TREE_TYPE (result),
509 se.expr));
510 gfc_add_expr_to_block (&se.pre, tmp);
511 gfc_add_block_to_block (&se.pre, &se.post);
513 tmp = gfc_generate_return ();
514 gfc_add_expr_to_block (&se.pre, tmp);
515 return gfc_finish_block (&se.pre);
518 return gfc_generate_return ();
522 /* Translate the PAUSE statement. We have to translate this statement
523 to a runtime library call. */
525 tree
526 gfc_trans_pause (gfc_code * code)
528 tree gfc_int4_type_node = gfc_get_int_type (4);
529 gfc_se se;
530 tree tmp;
532 /* Start a new block for this statement. */
533 gfc_init_se (&se, NULL);
534 gfc_start_block (&se.pre);
537 if (code->expr1 == NULL)
539 tmp = build_int_cst (gfc_int4_type_node, 0);
540 tmp = build_call_expr_loc (input_location,
541 gfor_fndecl_pause_string, 2,
542 build_int_cst (pchar_type_node, 0), tmp);
544 else if (code->expr1->ts.type == BT_INTEGER)
546 gfc_conv_expr (&se, code->expr1);
547 tmp = build_call_expr_loc (input_location,
548 gfor_fndecl_pause_numeric, 1,
549 fold_convert (gfc_int4_type_node, se.expr));
551 else
553 gfc_conv_expr_reference (&se, code->expr1);
554 tmp = build_call_expr_loc (input_location,
555 gfor_fndecl_pause_string, 2,
556 se.expr, se.string_length);
559 gfc_add_expr_to_block (&se.pre, tmp);
561 gfc_add_block_to_block (&se.pre, &se.post);
563 return gfc_finish_block (&se.pre);
567 /* Translate the STOP statement. We have to translate this statement
568 to a runtime library call. */
570 tree
571 gfc_trans_stop (gfc_code *code, bool error_stop)
573 tree gfc_int4_type_node = gfc_get_int_type (4);
574 gfc_se se;
575 tree tmp;
577 /* Start a new block for this statement. */
578 gfc_init_se (&se, NULL);
579 gfc_start_block (&se.pre);
581 if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
583 /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
584 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
585 tmp = build_call_expr_loc (input_location, tmp, 0);
586 gfc_add_expr_to_block (&se.pre, tmp);
588 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_finalize, 0);
589 gfc_add_expr_to_block (&se.pre, tmp);
592 if (code->expr1 == NULL)
594 tmp = build_int_cst (gfc_int4_type_node, 0);
595 tmp = build_call_expr_loc (input_location,
596 error_stop
597 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
598 ? gfor_fndecl_caf_error_stop_str
599 : gfor_fndecl_error_stop_string)
600 : gfor_fndecl_stop_string,
601 2, build_int_cst (pchar_type_node, 0), tmp);
603 else if (code->expr1->ts.type == BT_INTEGER)
605 gfc_conv_expr (&se, code->expr1);
606 tmp = build_call_expr_loc (input_location,
607 error_stop
608 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
609 ? gfor_fndecl_caf_error_stop
610 : gfor_fndecl_error_stop_numeric)
611 : gfor_fndecl_stop_numeric_f08, 1,
612 fold_convert (gfc_int4_type_node, se.expr));
614 else
616 gfc_conv_expr_reference (&se, code->expr1);
617 tmp = build_call_expr_loc (input_location,
618 error_stop
619 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
620 ? gfor_fndecl_caf_error_stop_str
621 : gfor_fndecl_error_stop_string)
622 : gfor_fndecl_stop_string,
623 2, se.expr, se.string_length);
626 gfc_add_expr_to_block (&se.pre, tmp);
628 gfc_add_block_to_block (&se.pre, &se.post);
630 return gfc_finish_block (&se.pre);
634 tree
635 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
637 gfc_se se, argse;
638 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
640 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
641 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
642 if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
643 return NULL_TREE;
645 gfc_init_se (&se, NULL);
646 gfc_start_block (&se.pre);
648 if (code->expr2)
650 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
651 gfc_init_se (&argse, NULL);
652 gfc_conv_expr_val (&argse, code->expr2);
653 stat = argse.expr;
656 if (code->expr4)
658 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
659 gfc_init_se (&argse, NULL);
660 gfc_conv_expr_val (&argse, code->expr4);
661 lock_acquired = argse.expr;
664 if (stat != NULL_TREE)
665 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
667 if (lock_acquired != NULL_TREE)
668 gfc_add_modify (&se.pre, lock_acquired,
669 fold_convert (TREE_TYPE (lock_acquired),
670 boolean_true_node));
672 return gfc_finish_block (&se.pre);
676 tree
677 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
679 gfc_se se, argse;
680 tree tmp;
681 tree images = NULL_TREE, stat = NULL_TREE,
682 errmsg = NULL_TREE, errmsglen = NULL_TREE;
684 /* Short cut: For single images without bound checking or without STAT=,
685 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
686 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
687 && gfc_option.coarray != GFC_FCOARRAY_LIB)
688 return NULL_TREE;
690 gfc_init_se (&se, NULL);
691 gfc_start_block (&se.pre);
693 if (code->expr1 && code->expr1->rank == 0)
695 gfc_init_se (&argse, NULL);
696 gfc_conv_expr_val (&argse, code->expr1);
697 images = argse.expr;
700 if (code->expr2)
702 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
703 gfc_init_se (&argse, NULL);
704 gfc_conv_expr_val (&argse, code->expr2);
705 stat = argse.expr;
707 else
708 stat = null_pointer_node;
710 if (code->expr3 && gfc_option.coarray == GFC_FCOARRAY_LIB
711 && type != EXEC_SYNC_MEMORY)
713 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
714 gfc_init_se (&argse, NULL);
715 gfc_conv_expr (&argse, code->expr3);
716 gfc_conv_string_parameter (&argse);
717 errmsg = gfc_build_addr_expr (NULL, argse.expr);
718 errmsglen = argse.string_length;
720 else if (gfc_option.coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY)
722 errmsg = null_pointer_node;
723 errmsglen = build_int_cst (integer_type_node, 0);
726 /* Check SYNC IMAGES(imageset) for valid image index.
727 FIXME: Add a check for image-set arrays. */
728 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
729 && code->expr1->rank == 0)
731 tree cond;
732 if (gfc_option.coarray != GFC_FCOARRAY_LIB)
733 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
734 images, build_int_cst (TREE_TYPE (images), 1));
735 else
737 tree cond2;
738 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
739 images, gfort_gvar_caf_num_images);
740 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
741 images,
742 build_int_cst (TREE_TYPE (images), 1));
743 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
744 boolean_type_node, cond, cond2);
746 gfc_trans_runtime_check (true, false, cond, &se.pre,
747 &code->expr1->where, "Invalid image number "
748 "%d in SYNC IMAGES",
749 fold_convert (integer_type_node, se.expr));
752 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
753 image control statements SYNC IMAGES and SYNC ALL. */
754 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
756 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
757 tmp = build_call_expr_loc (input_location, tmp, 0);
758 gfc_add_expr_to_block (&se.pre, tmp);
761 if (gfc_option.coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
763 /* Set STAT to zero. */
764 if (code->expr2)
765 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
767 else if (type == EXEC_SYNC_ALL)
769 /* SYNC ALL => stat == null_pointer_node
770 SYNC ALL(stat=s) => stat has an integer type
772 If "stat" has the wrong integer type, use a temp variable of
773 the right type and later cast the result back into "stat". */
774 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
776 if (TREE_TYPE (stat) == integer_type_node)
777 stat = gfc_build_addr_expr (NULL, stat);
779 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
780 3, stat, errmsg, errmsglen);
781 gfc_add_expr_to_block (&se.pre, tmp);
783 else
785 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
787 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
788 3, gfc_build_addr_expr (NULL, tmp_stat),
789 errmsg, errmsglen);
790 gfc_add_expr_to_block (&se.pre, tmp);
792 gfc_add_modify (&se.pre, stat,
793 fold_convert (TREE_TYPE (stat), tmp_stat));
796 else
798 tree len;
800 gcc_assert (type == EXEC_SYNC_IMAGES);
802 if (!code->expr1)
804 len = build_int_cst (integer_type_node, -1);
805 images = null_pointer_node;
807 else if (code->expr1->rank == 0)
809 len = build_int_cst (integer_type_node, 1);
810 images = gfc_build_addr_expr (NULL_TREE, images);
812 else
814 /* FIXME. */
815 if (code->expr1->ts.kind != gfc_c_int_kind)
816 gfc_fatal_error ("Sorry, only support for integer kind %d "
817 "implemented for image-set at %L",
818 gfc_c_int_kind, &code->expr1->where);
820 gfc_conv_array_parameter (&se, code->expr1,
821 gfc_walk_expr (code->expr1), true, NULL,
822 NULL, &len);
823 images = se.expr;
825 tmp = gfc_typenode_for_spec (&code->expr1->ts);
826 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
827 tmp = gfc_get_element_type (tmp);
829 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
830 TREE_TYPE (len), len,
831 fold_convert (TREE_TYPE (len),
832 TYPE_SIZE_UNIT (tmp)));
833 len = fold_convert (integer_type_node, len);
836 /* SYNC IMAGES(imgs) => stat == null_pointer_node
837 SYNC IMAGES(imgs,stat=s) => stat has an integer type
839 If "stat" has the wrong integer type, use a temp variable of
840 the right type and later cast the result back into "stat". */
841 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
843 if (TREE_TYPE (stat) == integer_type_node)
844 stat = gfc_build_addr_expr (NULL, stat);
846 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
847 5, fold_convert (integer_type_node, len),
848 images, stat, errmsg, errmsglen);
849 gfc_add_expr_to_block (&se.pre, tmp);
851 else
853 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
855 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
856 5, fold_convert (integer_type_node, len),
857 images, gfc_build_addr_expr (NULL, tmp_stat),
858 errmsg, errmsglen);
859 gfc_add_expr_to_block (&se.pre, tmp);
861 gfc_add_modify (&se.pre, stat,
862 fold_convert (TREE_TYPE (stat), tmp_stat));
866 return gfc_finish_block (&se.pre);
870 /* Generate GENERIC for the IF construct. This function also deals with
871 the simple IF statement, because the front end translates the IF
872 statement into an IF construct.
874 We translate:
876 IF (cond) THEN
877 then_clause
878 ELSEIF (cond2)
879 elseif_clause
880 ELSE
881 else_clause
882 ENDIF
884 into:
886 pre_cond_s;
887 if (cond_s)
889 then_clause;
891 else
893 pre_cond_s
894 if (cond_s)
896 elseif_clause
898 else
900 else_clause;
904 where COND_S is the simplified version of the predicate. PRE_COND_S
905 are the pre side-effects produced by the translation of the
906 conditional.
907 We need to build the chain recursively otherwise we run into
908 problems with folding incomplete statements. */
910 static tree
911 gfc_trans_if_1 (gfc_code * code)
913 gfc_se if_se;
914 tree stmt, elsestmt;
915 locus saved_loc;
916 location_t loc;
918 /* Check for an unconditional ELSE clause. */
919 if (!code->expr1)
920 return gfc_trans_code (code->next);
922 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
923 gfc_init_se (&if_se, NULL);
924 gfc_start_block (&if_se.pre);
926 /* Calculate the IF condition expression. */
927 if (code->expr1->where.lb)
929 gfc_save_backend_locus (&saved_loc);
930 gfc_set_backend_locus (&code->expr1->where);
933 gfc_conv_expr_val (&if_se, code->expr1);
935 if (code->expr1->where.lb)
936 gfc_restore_backend_locus (&saved_loc);
938 /* Translate the THEN clause. */
939 stmt = gfc_trans_code (code->next);
941 /* Translate the ELSE clause. */
942 if (code->block)
943 elsestmt = gfc_trans_if_1 (code->block);
944 else
945 elsestmt = build_empty_stmt (input_location);
947 /* Build the condition expression and add it to the condition block. */
948 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
949 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
950 elsestmt);
952 gfc_add_expr_to_block (&if_se.pre, stmt);
954 /* Finish off this statement. */
955 return gfc_finish_block (&if_se.pre);
958 tree
959 gfc_trans_if (gfc_code * code)
961 stmtblock_t body;
962 tree exit_label;
964 /* Create exit label so it is available for trans'ing the body code. */
965 exit_label = gfc_build_label_decl (NULL_TREE);
966 code->exit_label = exit_label;
968 /* Translate the actual code in code->block. */
969 gfc_init_block (&body);
970 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
972 /* Add exit label. */
973 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
975 return gfc_finish_block (&body);
979 /* Translate an arithmetic IF expression.
981 IF (cond) label1, label2, label3 translates to
983 if (cond <= 0)
985 if (cond < 0)
986 goto label1;
987 else // cond == 0
988 goto label2;
990 else // cond > 0
991 goto label3;
993 An optimized version can be generated in case of equal labels.
994 E.g., if label1 is equal to label2, we can translate it to
996 if (cond <= 0)
997 goto label1;
998 else
999 goto label3;
1002 tree
1003 gfc_trans_arithmetic_if (gfc_code * code)
1005 gfc_se se;
1006 tree tmp;
1007 tree branch1;
1008 tree branch2;
1009 tree zero;
1011 /* Start a new block. */
1012 gfc_init_se (&se, NULL);
1013 gfc_start_block (&se.pre);
1015 /* Pre-evaluate COND. */
1016 gfc_conv_expr_val (&se, code->expr1);
1017 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1019 /* Build something to compare with. */
1020 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1022 if (code->label1->value != code->label2->value)
1024 /* If (cond < 0) take branch1 else take branch2.
1025 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1026 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1027 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1029 if (code->label1->value != code->label3->value)
1030 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1031 se.expr, zero);
1032 else
1033 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1034 se.expr, zero);
1036 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1037 tmp, branch1, branch2);
1039 else
1040 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1042 if (code->label1->value != code->label3->value
1043 && code->label2->value != code->label3->value)
1045 /* if (cond <= 0) take branch1 else take branch2. */
1046 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1047 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1048 se.expr, zero);
1049 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1050 tmp, branch1, branch2);
1053 /* Append the COND_EXPR to the evaluation of COND, and return. */
1054 gfc_add_expr_to_block (&se.pre, branch1);
1055 return gfc_finish_block (&se.pre);
1059 /* Translate a CRITICAL block. */
1060 tree
1061 gfc_trans_critical (gfc_code *code)
1063 stmtblock_t block;
1064 tree tmp;
1066 gfc_start_block (&block);
1068 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1070 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_critical, 0);
1071 gfc_add_expr_to_block (&block, tmp);
1074 tmp = gfc_trans_code (code->block->next);
1075 gfc_add_expr_to_block (&block, tmp);
1077 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1079 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_critical,
1081 gfc_add_expr_to_block (&block, tmp);
1085 return gfc_finish_block (&block);
1089 /* Do proper initialization for ASSOCIATE names. */
1091 static void
1092 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1094 gfc_expr *e;
1095 tree tmp;
1097 gcc_assert (sym->assoc);
1098 e = sym->assoc->target;
1100 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1101 to array temporary) for arrays with either unknown shape or if associating
1102 to a variable. */
1103 if (sym->attr.dimension
1104 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1106 gfc_se se;
1107 gfc_ss *ss;
1108 tree desc;
1110 desc = sym->backend_decl;
1112 /* If association is to an expression, evaluate it and create temporary.
1113 Otherwise, get descriptor of target for pointer assignment. */
1114 gfc_init_se (&se, NULL);
1115 ss = gfc_walk_expr (e);
1116 if (sym->assoc->variable)
1118 se.direct_byref = 1;
1119 se.expr = desc;
1121 gfc_conv_expr_descriptor (&se, e, ss);
1123 /* If we didn't already do the pointer assignment, set associate-name
1124 descriptor to the one generated for the temporary. */
1125 if (!sym->assoc->variable)
1127 int dim;
1129 gfc_add_modify (&se.pre, desc, se.expr);
1131 /* The generated descriptor has lower bound zero (as array
1132 temporary), shift bounds so we get lower bounds of 1. */
1133 for (dim = 0; dim < e->rank; ++dim)
1134 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1135 dim, gfc_index_one_node);
1138 /* Done, register stuff as init / cleanup code. */
1139 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1140 gfc_finish_block (&se.post));
1143 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1144 else if (gfc_is_associate_pointer (sym))
1146 gfc_se se;
1148 gcc_assert (!sym->attr.dimension);
1150 gfc_init_se (&se, NULL);
1151 gfc_conv_expr (&se, e);
1153 tmp = TREE_TYPE (sym->backend_decl);
1154 tmp = gfc_build_addr_expr (tmp, se.expr);
1155 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1157 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1158 gfc_finish_block (&se.post));
1161 /* Do a simple assignment. This is for scalar expressions, where we
1162 can simply use expression assignment. */
1163 else
1165 gfc_expr *lhs;
1167 lhs = gfc_lval_expr_from_sym (sym);
1168 tmp = gfc_trans_assignment (lhs, e, false, true);
1169 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1174 /* Translate a BLOCK construct. This is basically what we would do for a
1175 procedure body. */
1177 tree
1178 gfc_trans_block_construct (gfc_code* code)
1180 gfc_namespace* ns;
1181 gfc_symbol* sym;
1182 gfc_wrapped_block block;
1183 tree exit_label;
1184 stmtblock_t body;
1185 gfc_association_list *ass;
1187 ns = code->ext.block.ns;
1188 gcc_assert (ns);
1189 sym = ns->proc_name;
1190 gcc_assert (sym);
1192 /* Process local variables. */
1193 gcc_assert (!sym->tlink);
1194 sym->tlink = sym;
1195 gfc_process_block_locals (ns);
1197 /* Generate code including exit-label. */
1198 gfc_init_block (&body);
1199 exit_label = gfc_build_label_decl (NULL_TREE);
1200 code->exit_label = exit_label;
1201 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1202 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1204 /* Finish everything. */
1205 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1206 gfc_trans_deferred_vars (sym, &block);
1207 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1208 trans_associate_var (ass->st->n.sym, &block);
1210 return gfc_finish_wrapped_block (&block);
1214 /* Translate the simple DO construct. This is where the loop variable has
1215 integer type and step +-1. We can't use this in the general case
1216 because integer overflow and floating point errors could give incorrect
1217 results.
1218 We translate a do loop from:
1220 DO dovar = from, to, step
1221 body
1222 END DO
1226 [Evaluate loop bounds and step]
1227 dovar = from;
1228 if ((step > 0) ? (dovar <= to) : (dovar => to))
1230 for (;;)
1232 body;
1233 cycle_label:
1234 cond = (dovar == to);
1235 dovar += step;
1236 if (cond) goto end_label;
1239 end_label:
1241 This helps the optimizers by avoiding the extra induction variable
1242 used in the general case. */
1244 static tree
1245 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1246 tree from, tree to, tree step, tree exit_cond)
1248 stmtblock_t body;
1249 tree type;
1250 tree cond;
1251 tree tmp;
1252 tree saved_dovar = NULL;
1253 tree cycle_label;
1254 tree exit_label;
1255 location_t loc;
1257 type = TREE_TYPE (dovar);
1259 loc = code->ext.iterator->start->where.lb->location;
1261 /* Initialize the DO variable: dovar = from. */
1262 gfc_add_modify_loc (loc, pblock, dovar, from);
1264 /* Save value for do-tinkering checking. */
1265 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1267 saved_dovar = gfc_create_var (type, ".saved_dovar");
1268 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1271 /* Cycle and exit statements are implemented with gotos. */
1272 cycle_label = gfc_build_label_decl (NULL_TREE);
1273 exit_label = gfc_build_label_decl (NULL_TREE);
1275 /* Put the labels where they can be found later. See gfc_trans_do(). */
1276 code->cycle_label = cycle_label;
1277 code->exit_label = exit_label;
1279 /* Loop body. */
1280 gfc_start_block (&body);
1282 /* Main loop body. */
1283 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1284 gfc_add_expr_to_block (&body, tmp);
1286 /* Label for cycle statements (if needed). */
1287 if (TREE_USED (cycle_label))
1289 tmp = build1_v (LABEL_EXPR, cycle_label);
1290 gfc_add_expr_to_block (&body, tmp);
1293 /* Check whether someone has modified the loop variable. */
1294 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1296 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1297 dovar, saved_dovar);
1298 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1299 "Loop variable has been modified");
1302 /* Exit the loop if there is an I/O result condition or error. */
1303 if (exit_cond)
1305 tmp = build1_v (GOTO_EXPR, exit_label);
1306 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1307 exit_cond, tmp,
1308 build_empty_stmt (loc));
1309 gfc_add_expr_to_block (&body, tmp);
1312 /* Evaluate the loop condition. */
1313 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1314 to);
1315 cond = gfc_evaluate_now_loc (loc, cond, &body);
1317 /* Increment the loop variable. */
1318 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1319 gfc_add_modify_loc (loc, &body, dovar, tmp);
1321 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1322 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1324 /* The loop exit. */
1325 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1326 TREE_USED (exit_label) = 1;
1327 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1328 cond, tmp, build_empty_stmt (loc));
1329 gfc_add_expr_to_block (&body, tmp);
1331 /* Finish the loop body. */
1332 tmp = gfc_finish_block (&body);
1333 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1335 /* Only execute the loop if the number of iterations is positive. */
1336 if (tree_int_cst_sgn (step) > 0)
1337 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1338 to);
1339 else
1340 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1341 to);
1342 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1343 build_empty_stmt (loc));
1344 gfc_add_expr_to_block (pblock, tmp);
1346 /* Add the exit label. */
1347 tmp = build1_v (LABEL_EXPR, exit_label);
1348 gfc_add_expr_to_block (pblock, tmp);
1350 return gfc_finish_block (pblock);
1353 /* Translate the DO construct. This obviously is one of the most
1354 important ones to get right with any compiler, but especially
1355 so for Fortran.
1357 We special case some loop forms as described in gfc_trans_simple_do.
1358 For other cases we implement them with a separate loop count,
1359 as described in the standard.
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 empty = (step > 0 ? to < from : to > from);
1371 countm1 = (to - from) / step;
1372 dovar = from;
1373 if (empty) goto exit_label;
1374 for (;;)
1376 body;
1377 cycle_label:
1378 dovar += step
1379 if (countm1 ==0) goto exit_label;
1380 countm1--;
1382 exit_label:
1384 countm1 is an unsigned integer. It is equal to the loop count minus one,
1385 because the loop count itself can overflow. */
1387 tree
1388 gfc_trans_do (gfc_code * code, tree exit_cond)
1390 gfc_se se;
1391 tree dovar;
1392 tree saved_dovar = NULL;
1393 tree from;
1394 tree to;
1395 tree step;
1396 tree countm1;
1397 tree type;
1398 tree utype;
1399 tree cond;
1400 tree cycle_label;
1401 tree exit_label;
1402 tree tmp;
1403 tree pos_step;
1404 stmtblock_t block;
1405 stmtblock_t body;
1406 location_t loc;
1408 gfc_start_block (&block);
1410 loc = code->ext.iterator->start->where.lb->location;
1412 /* Evaluate all the expressions in the iterator. */
1413 gfc_init_se (&se, NULL);
1414 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1415 gfc_add_block_to_block (&block, &se.pre);
1416 dovar = se.expr;
1417 type = TREE_TYPE (dovar);
1419 gfc_init_se (&se, NULL);
1420 gfc_conv_expr_val (&se, code->ext.iterator->start);
1421 gfc_add_block_to_block (&block, &se.pre);
1422 from = gfc_evaluate_now (se.expr, &block);
1424 gfc_init_se (&se, NULL);
1425 gfc_conv_expr_val (&se, code->ext.iterator->end);
1426 gfc_add_block_to_block (&block, &se.pre);
1427 to = gfc_evaluate_now (se.expr, &block);
1429 gfc_init_se (&se, NULL);
1430 gfc_conv_expr_val (&se, code->ext.iterator->step);
1431 gfc_add_block_to_block (&block, &se.pre);
1432 step = gfc_evaluate_now (se.expr, &block);
1434 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1436 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1437 build_zero_cst (type));
1438 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1439 "DO step value is zero");
1442 /* Special case simple loops. */
1443 if (TREE_CODE (type) == INTEGER_TYPE
1444 && (integer_onep (step)
1445 || tree_int_cst_equal (step, integer_minus_one_node)))
1446 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1448 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1449 build_zero_cst (type));
1451 if (TREE_CODE (type) == INTEGER_TYPE)
1452 utype = unsigned_type_for (type);
1453 else
1454 utype = unsigned_type_for (gfc_array_index_type);
1455 countm1 = gfc_create_var (utype, "countm1");
1457 /* Cycle and exit statements are implemented with gotos. */
1458 cycle_label = gfc_build_label_decl (NULL_TREE);
1459 exit_label = gfc_build_label_decl (NULL_TREE);
1460 TREE_USED (exit_label) = 1;
1462 /* Put these labels where they can be found later. */
1463 code->cycle_label = cycle_label;
1464 code->exit_label = exit_label;
1466 /* Initialize the DO variable: dovar = from. */
1467 gfc_add_modify (&block, dovar, from);
1469 /* Save value for do-tinkering checking. */
1470 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1472 saved_dovar = gfc_create_var (type, ".saved_dovar");
1473 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1476 /* Initialize loop count and jump to exit label if the loop is empty.
1477 This code is executed before we enter the loop body. We generate:
1478 step_sign = sign(1,step);
1479 if (step > 0)
1481 if (to < from)
1482 goto exit_label;
1484 else
1486 if (to > from)
1487 goto exit_label;
1489 countm1 = (to*step_sign - from*step_sign) / (step*step_sign);
1493 if (TREE_CODE (type) == INTEGER_TYPE)
1495 tree pos, neg, step_sign, to2, from2, step2;
1497 /* Calculate SIGN (1,step), as (step < 0 ? -1 : 1) */
1499 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1500 build_int_cst (TREE_TYPE (step), 0));
1501 step_sign = fold_build3_loc (loc, COND_EXPR, type, tmp,
1502 build_int_cst (type, -1),
1503 build_int_cst (type, 1));
1505 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1506 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1507 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1508 exit_label),
1509 build_empty_stmt (loc));
1511 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to,
1512 from);
1513 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1514 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1515 exit_label),
1516 build_empty_stmt (loc));
1517 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1518 pos_step, pos, neg);
1520 gfc_add_expr_to_block (&block, tmp);
1522 /* Calculate the loop count. to-from can overflow, so
1523 we cast to unsigned. */
1525 to2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, to);
1526 from2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, from);
1527 step2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, step);
1528 step2 = fold_convert (utype, step2);
1529 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to2, from2);
1530 tmp = fold_convert (utype, tmp);
1531 tmp = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype, tmp, step2);
1532 tmp = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, countm1, tmp);
1533 gfc_add_expr_to_block (&block, tmp);
1535 else
1537 /* TODO: We could use the same width as the real type.
1538 This would probably cause more problems that it solves
1539 when we implement "long double" types. */
1541 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1542 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1543 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1544 gfc_add_modify (&block, countm1, tmp);
1546 /* We need a special check for empty loops:
1547 empty = (step > 0 ? to < from : to > from); */
1548 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1549 fold_build2_loc (loc, LT_EXPR,
1550 boolean_type_node, to, from),
1551 fold_build2_loc (loc, GT_EXPR,
1552 boolean_type_node, to, from));
1553 /* If the loop is empty, go directly to the exit label. */
1554 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1555 build1_v (GOTO_EXPR, exit_label),
1556 build_empty_stmt (input_location));
1557 gfc_add_expr_to_block (&block, tmp);
1560 /* Loop body. */
1561 gfc_start_block (&body);
1563 /* Main loop body. */
1564 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1565 gfc_add_expr_to_block (&body, tmp);
1567 /* Label for cycle statements (if needed). */
1568 if (TREE_USED (cycle_label))
1570 tmp = build1_v (LABEL_EXPR, cycle_label);
1571 gfc_add_expr_to_block (&body, tmp);
1574 /* Check whether someone has modified the loop variable. */
1575 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1577 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1578 saved_dovar);
1579 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1580 "Loop variable has been modified");
1583 /* Exit the loop if there is an I/O result condition or error. */
1584 if (exit_cond)
1586 tmp = build1_v (GOTO_EXPR, exit_label);
1587 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1588 exit_cond, tmp,
1589 build_empty_stmt (input_location));
1590 gfc_add_expr_to_block (&body, tmp);
1593 /* Increment the loop variable. */
1594 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1595 gfc_add_modify_loc (loc, &body, dovar, tmp);
1597 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1598 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1600 /* End with the loop condition. Loop until countm1 == 0. */
1601 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1,
1602 build_int_cst (utype, 0));
1603 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1604 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1605 cond, tmp, build_empty_stmt (loc));
1606 gfc_add_expr_to_block (&body, tmp);
1608 /* Decrement the loop count. */
1609 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1610 build_int_cst (utype, 1));
1611 gfc_add_modify_loc (loc, &body, countm1, tmp);
1613 /* End of loop body. */
1614 tmp = gfc_finish_block (&body);
1616 /* The for loop itself. */
1617 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1618 gfc_add_expr_to_block (&block, tmp);
1620 /* Add the exit label. */
1621 tmp = build1_v (LABEL_EXPR, exit_label);
1622 gfc_add_expr_to_block (&block, tmp);
1624 return gfc_finish_block (&block);
1628 /* Translate the DO WHILE construct.
1630 We translate
1632 DO WHILE (cond)
1633 body
1634 END DO
1638 for ( ; ; )
1640 pre_cond;
1641 if (! cond) goto exit_label;
1642 body;
1643 cycle_label:
1645 exit_label:
1647 Because the evaluation of the exit condition `cond' may have side
1648 effects, we can't do much for empty loop bodies. The backend optimizers
1649 should be smart enough to eliminate any dead loops. */
1651 tree
1652 gfc_trans_do_while (gfc_code * code)
1654 gfc_se cond;
1655 tree tmp;
1656 tree cycle_label;
1657 tree exit_label;
1658 stmtblock_t block;
1660 /* Everything we build here is part of the loop body. */
1661 gfc_start_block (&block);
1663 /* Cycle and exit statements are implemented with gotos. */
1664 cycle_label = gfc_build_label_decl (NULL_TREE);
1665 exit_label = gfc_build_label_decl (NULL_TREE);
1667 /* Put the labels where they can be found later. See gfc_trans_do(). */
1668 code->cycle_label = cycle_label;
1669 code->exit_label = exit_label;
1671 /* Create a GIMPLE version of the exit condition. */
1672 gfc_init_se (&cond, NULL);
1673 gfc_conv_expr_val (&cond, code->expr1);
1674 gfc_add_block_to_block (&block, &cond.pre);
1675 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1676 TRUTH_NOT_EXPR, boolean_type_node, cond.expr);
1678 /* Build "IF (! cond) GOTO exit_label". */
1679 tmp = build1_v (GOTO_EXPR, exit_label);
1680 TREE_USED (exit_label) = 1;
1681 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1682 void_type_node, cond.expr, tmp,
1683 build_empty_stmt (code->expr1->where.lb->location));
1684 gfc_add_expr_to_block (&block, tmp);
1686 /* The main body of the loop. */
1687 tmp = gfc_trans_code (code->block->next);
1688 gfc_add_expr_to_block (&block, tmp);
1690 /* Label for cycle statements (if needed). */
1691 if (TREE_USED (cycle_label))
1693 tmp = build1_v (LABEL_EXPR, cycle_label);
1694 gfc_add_expr_to_block (&block, tmp);
1697 /* End of loop body. */
1698 tmp = gfc_finish_block (&block);
1700 gfc_init_block (&block);
1701 /* Build the loop. */
1702 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1703 void_type_node, tmp);
1704 gfc_add_expr_to_block (&block, tmp);
1706 /* Add the exit label. */
1707 tmp = build1_v (LABEL_EXPR, exit_label);
1708 gfc_add_expr_to_block (&block, tmp);
1710 return gfc_finish_block (&block);
1714 /* Translate the SELECT CASE construct for INTEGER case expressions,
1715 without killing all potential optimizations. The problem is that
1716 Fortran allows unbounded cases, but the back-end does not, so we
1717 need to intercept those before we enter the equivalent SWITCH_EXPR
1718 we can build.
1720 For example, we translate this,
1722 SELECT CASE (expr)
1723 CASE (:100,101,105:115)
1724 block_1
1725 CASE (190:199,200:)
1726 block_2
1727 CASE (300)
1728 block_3
1729 CASE DEFAULT
1730 block_4
1731 END SELECT
1733 to the GENERIC equivalent,
1735 switch (expr)
1737 case (minimum value for typeof(expr) ... 100:
1738 case 101:
1739 case 105 ... 114:
1740 block1:
1741 goto end_label;
1743 case 200 ... (maximum value for typeof(expr):
1744 case 190 ... 199:
1745 block2;
1746 goto end_label;
1748 case 300:
1749 block_3;
1750 goto end_label;
1752 default:
1753 block_4;
1754 goto end_label;
1757 end_label: */
1759 static tree
1760 gfc_trans_integer_select (gfc_code * code)
1762 gfc_code *c;
1763 gfc_case *cp;
1764 tree end_label;
1765 tree tmp;
1766 gfc_se se;
1767 stmtblock_t block;
1768 stmtblock_t body;
1770 gfc_start_block (&block);
1772 /* Calculate the switch expression. */
1773 gfc_init_se (&se, NULL);
1774 gfc_conv_expr_val (&se, code->expr1);
1775 gfc_add_block_to_block (&block, &se.pre);
1777 end_label = gfc_build_label_decl (NULL_TREE);
1779 gfc_init_block (&body);
1781 for (c = code->block; c; c = c->block)
1783 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1785 tree low, high;
1786 tree label;
1788 /* Assume it's the default case. */
1789 low = high = NULL_TREE;
1791 if (cp->low)
1793 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1794 cp->low->ts.kind);
1796 /* If there's only a lower bound, set the high bound to the
1797 maximum value of the case expression. */
1798 if (!cp->high)
1799 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1802 if (cp->high)
1804 /* Three cases are possible here:
1806 1) There is no lower bound, e.g. CASE (:N).
1807 2) There is a lower bound .NE. high bound, that is
1808 a case range, e.g. CASE (N:M) where M>N (we make
1809 sure that M>N during type resolution).
1810 3) There is a lower bound, and it has the same value
1811 as the high bound, e.g. CASE (N:N). This is our
1812 internal representation of CASE(N).
1814 In the first and second case, we need to set a value for
1815 high. In the third case, we don't because the GCC middle
1816 end represents a single case value by just letting high be
1817 a NULL_TREE. We can't do that because we need to be able
1818 to represent unbounded cases. */
1820 if (!cp->low
1821 || (cp->low
1822 && mpz_cmp (cp->low->value.integer,
1823 cp->high->value.integer) != 0))
1824 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1825 cp->high->ts.kind);
1827 /* Unbounded case. */
1828 if (!cp->low)
1829 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1832 /* Build a label. */
1833 label = gfc_build_label_decl (NULL_TREE);
1835 /* Add this case label.
1836 Add parameter 'label', make it match GCC backend. */
1837 tmp = build_case_label (low, high, label);
1838 gfc_add_expr_to_block (&body, tmp);
1841 /* Add the statements for this case. */
1842 tmp = gfc_trans_code (c->next);
1843 gfc_add_expr_to_block (&body, tmp);
1845 /* Break to the end of the construct. */
1846 tmp = build1_v (GOTO_EXPR, end_label);
1847 gfc_add_expr_to_block (&body, tmp);
1850 tmp = gfc_finish_block (&body);
1851 tmp = build3_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE);
1852 gfc_add_expr_to_block (&block, tmp);
1854 tmp = build1_v (LABEL_EXPR, end_label);
1855 gfc_add_expr_to_block (&block, tmp);
1857 return gfc_finish_block (&block);
1861 /* Translate the SELECT CASE construct for LOGICAL case expressions.
1863 There are only two cases possible here, even though the standard
1864 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
1865 .FALSE., and DEFAULT.
1867 We never generate more than two blocks here. Instead, we always
1868 try to eliminate the DEFAULT case. This way, we can translate this
1869 kind of SELECT construct to a simple
1871 if {} else {};
1873 expression in GENERIC. */
1875 static tree
1876 gfc_trans_logical_select (gfc_code * code)
1878 gfc_code *c;
1879 gfc_code *t, *f, *d;
1880 gfc_case *cp;
1881 gfc_se se;
1882 stmtblock_t block;
1884 /* Assume we don't have any cases at all. */
1885 t = f = d = NULL;
1887 /* Now see which ones we actually do have. We can have at most two
1888 cases in a single case list: one for .TRUE. and one for .FALSE.
1889 The default case is always separate. If the cases for .TRUE. and
1890 .FALSE. are in the same case list, the block for that case list
1891 always executed, and we don't generate code a COND_EXPR. */
1892 for (c = code->block; c; c = c->block)
1894 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1896 if (cp->low)
1898 if (cp->low->value.logical == 0) /* .FALSE. */
1899 f = c;
1900 else /* if (cp->value.logical != 0), thus .TRUE. */
1901 t = c;
1903 else
1904 d = c;
1908 /* Start a new block. */
1909 gfc_start_block (&block);
1911 /* Calculate the switch expression. We always need to do this
1912 because it may have side effects. */
1913 gfc_init_se (&se, NULL);
1914 gfc_conv_expr_val (&se, code->expr1);
1915 gfc_add_block_to_block (&block, &se.pre);
1917 if (t == f && t != NULL)
1919 /* Cases for .TRUE. and .FALSE. are in the same block. Just
1920 translate the code for these cases, append it to the current
1921 block. */
1922 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
1924 else
1926 tree true_tree, false_tree, stmt;
1928 true_tree = build_empty_stmt (input_location);
1929 false_tree = build_empty_stmt (input_location);
1931 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
1932 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
1933 make the missing case the default case. */
1934 if (t != NULL && f != NULL)
1935 d = NULL;
1936 else if (d != NULL)
1938 if (t == NULL)
1939 t = d;
1940 else
1941 f = d;
1944 /* Translate the code for each of these blocks, and append it to
1945 the current block. */
1946 if (t != NULL)
1947 true_tree = gfc_trans_code (t->next);
1949 if (f != NULL)
1950 false_tree = gfc_trans_code (f->next);
1952 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1953 se.expr, true_tree, false_tree);
1954 gfc_add_expr_to_block (&block, stmt);
1957 return gfc_finish_block (&block);
1961 /* The jump table types are stored in static variables to avoid
1962 constructing them from scratch every single time. */
1963 static GTY(()) tree select_struct[2];
1965 /* Translate the SELECT CASE construct for CHARACTER case expressions.
1966 Instead of generating compares and jumps, it is far simpler to
1967 generate a data structure describing the cases in order and call a
1968 library subroutine that locates the right case.
1969 This is particularly true because this is the only case where we
1970 might have to dispose of a temporary.
1971 The library subroutine returns a pointer to jump to or NULL if no
1972 branches are to be taken. */
1974 static tree
1975 gfc_trans_character_select (gfc_code *code)
1977 tree init, end_label, tmp, type, case_num, label, fndecl;
1978 stmtblock_t block, body;
1979 gfc_case *cp, *d;
1980 gfc_code *c;
1981 gfc_se se, expr1se;
1982 int n, k;
1983 VEC(constructor_elt,gc) *inits = NULL;
1985 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
1987 /* The jump table types are stored in static variables to avoid
1988 constructing them from scratch every single time. */
1989 static tree ss_string1[2], ss_string1_len[2];
1990 static tree ss_string2[2], ss_string2_len[2];
1991 static tree ss_target[2];
1993 cp = code->block->ext.block.case_list;
1994 while (cp->left != NULL)
1995 cp = cp->left;
1997 /* Generate the body */
1998 gfc_start_block (&block);
1999 gfc_init_se (&expr1se, NULL);
2000 gfc_conv_expr_reference (&expr1se, code->expr1);
2002 gfc_add_block_to_block (&block, &expr1se.pre);
2004 end_label = gfc_build_label_decl (NULL_TREE);
2006 gfc_init_block (&body);
2008 /* Attempt to optimize length 1 selects. */
2009 if (integer_onep (expr1se.string_length))
2011 for (d = cp; d; d = d->right)
2013 int i;
2014 if (d->low)
2016 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2017 && d->low->ts.type == BT_CHARACTER);
2018 if (d->low->value.character.length > 1)
2020 for (i = 1; i < d->low->value.character.length; i++)
2021 if (d->low->value.character.string[i] != ' ')
2022 break;
2023 if (i != d->low->value.character.length)
2025 if (optimize && d->high && i == 1)
2027 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2028 && d->high->ts.type == BT_CHARACTER);
2029 if (d->high->value.character.length > 1
2030 && (d->low->value.character.string[0]
2031 == d->high->value.character.string[0])
2032 && d->high->value.character.string[1] != ' '
2033 && ((d->low->value.character.string[1] < ' ')
2034 == (d->high->value.character.string[1]
2035 < ' ')))
2036 continue;
2038 break;
2042 if (d->high)
2044 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2045 && d->high->ts.type == BT_CHARACTER);
2046 if (d->high->value.character.length > 1)
2048 for (i = 1; i < d->high->value.character.length; i++)
2049 if (d->high->value.character.string[i] != ' ')
2050 break;
2051 if (i != d->high->value.character.length)
2052 break;
2056 if (d == NULL)
2058 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2060 for (c = code->block; c; c = c->block)
2062 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2064 tree low, high;
2065 tree label;
2066 gfc_char_t r;
2068 /* Assume it's the default case. */
2069 low = high = NULL_TREE;
2071 if (cp->low)
2073 /* CASE ('ab') or CASE ('ab':'az') will never match
2074 any length 1 character. */
2075 if (cp->low->value.character.length > 1
2076 && cp->low->value.character.string[1] != ' ')
2077 continue;
2079 if (cp->low->value.character.length > 0)
2080 r = cp->low->value.character.string[0];
2081 else
2082 r = ' ';
2083 low = build_int_cst (ctype, r);
2085 /* If there's only a lower bound, set the high bound
2086 to the maximum value of the case expression. */
2087 if (!cp->high)
2088 high = TYPE_MAX_VALUE (ctype);
2091 if (cp->high)
2093 if (!cp->low
2094 || (cp->low->value.character.string[0]
2095 != cp->high->value.character.string[0]))
2097 if (cp->high->value.character.length > 0)
2098 r = cp->high->value.character.string[0];
2099 else
2100 r = ' ';
2101 high = build_int_cst (ctype, r);
2104 /* Unbounded case. */
2105 if (!cp->low)
2106 low = TYPE_MIN_VALUE (ctype);
2109 /* Build a label. */
2110 label = gfc_build_label_decl (NULL_TREE);
2112 /* Add this case label.
2113 Add parameter 'label', make it match GCC backend. */
2114 tmp = build_case_label (low, high, label);
2115 gfc_add_expr_to_block (&body, tmp);
2118 /* Add the statements for this case. */
2119 tmp = gfc_trans_code (c->next);
2120 gfc_add_expr_to_block (&body, tmp);
2122 /* Break to the end of the construct. */
2123 tmp = build1_v (GOTO_EXPR, end_label);
2124 gfc_add_expr_to_block (&body, tmp);
2127 tmp = gfc_string_to_single_character (expr1se.string_length,
2128 expr1se.expr,
2129 code->expr1->ts.kind);
2130 case_num = gfc_create_var (ctype, "case_num");
2131 gfc_add_modify (&block, case_num, tmp);
2133 gfc_add_block_to_block (&block, &expr1se.post);
2135 tmp = gfc_finish_block (&body);
2136 tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE);
2137 gfc_add_expr_to_block (&block, tmp);
2139 tmp = build1_v (LABEL_EXPR, end_label);
2140 gfc_add_expr_to_block (&block, tmp);
2142 return gfc_finish_block (&block);
2146 if (code->expr1->ts.kind == 1)
2147 k = 0;
2148 else if (code->expr1->ts.kind == 4)
2149 k = 1;
2150 else
2151 gcc_unreachable ();
2153 if (select_struct[k] == NULL)
2155 tree *chain = NULL;
2156 select_struct[k] = make_node (RECORD_TYPE);
2158 if (code->expr1->ts.kind == 1)
2159 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2160 else if (code->expr1->ts.kind == 4)
2161 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2162 else
2163 gcc_unreachable ();
2165 #undef ADD_FIELD
2166 #define ADD_FIELD(NAME, TYPE) \
2167 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2168 get_identifier (stringize(NAME)), \
2169 TYPE, \
2170 &chain)
2172 ADD_FIELD (string1, pchartype);
2173 ADD_FIELD (string1_len, gfc_charlen_type_node);
2175 ADD_FIELD (string2, pchartype);
2176 ADD_FIELD (string2_len, gfc_charlen_type_node);
2178 ADD_FIELD (target, integer_type_node);
2179 #undef ADD_FIELD
2181 gfc_finish_type (select_struct[k]);
2184 n = 0;
2185 for (d = cp; d; d = d->right)
2186 d->n = n++;
2188 for (c = code->block; c; c = c->block)
2190 for (d = c->ext.block.case_list; d; d = d->next)
2192 label = gfc_build_label_decl (NULL_TREE);
2193 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2194 ? NULL
2195 : build_int_cst (integer_type_node, d->n),
2196 NULL, label);
2197 gfc_add_expr_to_block (&body, tmp);
2200 tmp = gfc_trans_code (c->next);
2201 gfc_add_expr_to_block (&body, tmp);
2203 tmp = build1_v (GOTO_EXPR, end_label);
2204 gfc_add_expr_to_block (&body, tmp);
2207 /* Generate the structure describing the branches */
2208 for (d = cp; d; d = d->right)
2210 VEC(constructor_elt,gc) *node = NULL;
2212 gfc_init_se (&se, NULL);
2214 if (d->low == NULL)
2216 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2217 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2219 else
2221 gfc_conv_expr_reference (&se, d->low);
2223 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2224 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2227 if (d->high == NULL)
2229 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2230 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2232 else
2234 gfc_init_se (&se, NULL);
2235 gfc_conv_expr_reference (&se, d->high);
2237 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2238 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2241 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2242 build_int_cst (integer_type_node, d->n));
2244 tmp = build_constructor (select_struct[k], node);
2245 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2248 type = build_array_type (select_struct[k],
2249 build_index_type (size_int (n-1)));
2251 init = build_constructor (type, inits);
2252 TREE_CONSTANT (init) = 1;
2253 TREE_STATIC (init) = 1;
2254 /* Create a static variable to hold the jump table. */
2255 tmp = gfc_create_var (type, "jumptable");
2256 TREE_CONSTANT (tmp) = 1;
2257 TREE_STATIC (tmp) = 1;
2258 TREE_READONLY (tmp) = 1;
2259 DECL_INITIAL (tmp) = init;
2260 init = tmp;
2262 /* Build the library call */
2263 init = gfc_build_addr_expr (pvoid_type_node, init);
2265 if (code->expr1->ts.kind == 1)
2266 fndecl = gfor_fndecl_select_string;
2267 else if (code->expr1->ts.kind == 4)
2268 fndecl = gfor_fndecl_select_string_char4;
2269 else
2270 gcc_unreachable ();
2272 tmp = build_call_expr_loc (input_location,
2273 fndecl, 4, init,
2274 build_int_cst (gfc_charlen_type_node, n),
2275 expr1se.expr, expr1se.string_length);
2276 case_num = gfc_create_var (integer_type_node, "case_num");
2277 gfc_add_modify (&block, case_num, tmp);
2279 gfc_add_block_to_block (&block, &expr1se.post);
2281 tmp = gfc_finish_block (&body);
2282 tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE);
2283 gfc_add_expr_to_block (&block, tmp);
2285 tmp = build1_v (LABEL_EXPR, end_label);
2286 gfc_add_expr_to_block (&block, tmp);
2288 return gfc_finish_block (&block);
2292 /* Translate the three variants of the SELECT CASE construct.
2294 SELECT CASEs with INTEGER case expressions can be translated to an
2295 equivalent GENERIC switch statement, and for LOGICAL case
2296 expressions we build one or two if-else compares.
2298 SELECT CASEs with CHARACTER case expressions are a whole different
2299 story, because they don't exist in GENERIC. So we sort them and
2300 do a binary search at runtime.
2302 Fortran has no BREAK statement, and it does not allow jumps from
2303 one case block to another. That makes things a lot easier for
2304 the optimizers. */
2306 tree
2307 gfc_trans_select (gfc_code * code)
2309 stmtblock_t block;
2310 tree body;
2311 tree exit_label;
2313 gcc_assert (code && code->expr1);
2314 gfc_init_block (&block);
2316 /* Build the exit label and hang it in. */
2317 exit_label = gfc_build_label_decl (NULL_TREE);
2318 code->exit_label = exit_label;
2320 /* Empty SELECT constructs are legal. */
2321 if (code->block == NULL)
2322 body = build_empty_stmt (input_location);
2324 /* Select the correct translation function. */
2325 else
2326 switch (code->expr1->ts.type)
2328 case BT_LOGICAL:
2329 body = gfc_trans_logical_select (code);
2330 break;
2332 case BT_INTEGER:
2333 body = gfc_trans_integer_select (code);
2334 break;
2336 case BT_CHARACTER:
2337 body = gfc_trans_character_select (code);
2338 break;
2340 default:
2341 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2342 /* Not reached */
2345 /* Build everything together. */
2346 gfc_add_expr_to_block (&block, body);
2347 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2349 return gfc_finish_block (&block);
2353 /* Traversal function to substitute a replacement symtree if the symbol
2354 in the expression is the same as that passed. f == 2 signals that
2355 that variable itself is not to be checked - only the references.
2356 This group of functions is used when the variable expression in a
2357 FORALL assignment has internal references. For example:
2358 FORALL (i = 1:4) p(p(i)) = i
2359 The only recourse here is to store a copy of 'p' for the index
2360 expression. */
2362 static gfc_symtree *new_symtree;
2363 static gfc_symtree *old_symtree;
2365 static bool
2366 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2368 if (expr->expr_type != EXPR_VARIABLE)
2369 return false;
2371 if (*f == 2)
2372 *f = 1;
2373 else if (expr->symtree->n.sym == sym)
2374 expr->symtree = new_symtree;
2376 return false;
2379 static void
2380 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2382 gfc_traverse_expr (e, sym, forall_replace, f);
2385 static bool
2386 forall_restore (gfc_expr *expr,
2387 gfc_symbol *sym ATTRIBUTE_UNUSED,
2388 int *f ATTRIBUTE_UNUSED)
2390 if (expr->expr_type != EXPR_VARIABLE)
2391 return false;
2393 if (expr->symtree == new_symtree)
2394 expr->symtree = old_symtree;
2396 return false;
2399 static void
2400 forall_restore_symtree (gfc_expr *e)
2402 gfc_traverse_expr (e, NULL, forall_restore, 0);
2405 static void
2406 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2408 gfc_se tse;
2409 gfc_se rse;
2410 gfc_expr *e;
2411 gfc_symbol *new_sym;
2412 gfc_symbol *old_sym;
2413 gfc_symtree *root;
2414 tree tmp;
2416 /* Build a copy of the lvalue. */
2417 old_symtree = c->expr1->symtree;
2418 old_sym = old_symtree->n.sym;
2419 e = gfc_lval_expr_from_sym (old_sym);
2420 if (old_sym->attr.dimension)
2422 gfc_init_se (&tse, NULL);
2423 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2424 gfc_add_block_to_block (pre, &tse.pre);
2425 gfc_add_block_to_block (post, &tse.post);
2426 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2428 if (e->ts.type != BT_CHARACTER)
2430 /* Use the variable offset for the temporary. */
2431 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2432 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2435 else
2437 gfc_init_se (&tse, NULL);
2438 gfc_init_se (&rse, NULL);
2439 gfc_conv_expr (&rse, e);
2440 if (e->ts.type == BT_CHARACTER)
2442 tse.string_length = rse.string_length;
2443 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2444 tse.string_length);
2445 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2446 rse.string_length);
2447 gfc_add_block_to_block (pre, &tse.pre);
2448 gfc_add_block_to_block (post, &tse.post);
2450 else
2452 tmp = gfc_typenode_for_spec (&e->ts);
2453 tse.expr = gfc_create_var (tmp, "temp");
2456 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2457 e->expr_type == EXPR_VARIABLE, true);
2458 gfc_add_expr_to_block (pre, tmp);
2460 gfc_free_expr (e);
2462 /* Create a new symbol to represent the lvalue. */
2463 new_sym = gfc_new_symbol (old_sym->name, NULL);
2464 new_sym->ts = old_sym->ts;
2465 new_sym->attr.referenced = 1;
2466 new_sym->attr.temporary = 1;
2467 new_sym->attr.dimension = old_sym->attr.dimension;
2468 new_sym->attr.flavor = old_sym->attr.flavor;
2470 /* Use the temporary as the backend_decl. */
2471 new_sym->backend_decl = tse.expr;
2473 /* Create a fake symtree for it. */
2474 root = NULL;
2475 new_symtree = gfc_new_symtree (&root, old_sym->name);
2476 new_symtree->n.sym = new_sym;
2477 gcc_assert (new_symtree == root);
2479 /* Go through the expression reference replacing the old_symtree
2480 with the new. */
2481 forall_replace_symtree (c->expr1, old_sym, 2);
2483 /* Now we have made this temporary, we might as well use it for
2484 the right hand side. */
2485 forall_replace_symtree (c->expr2, old_sym, 1);
2489 /* Handles dependencies in forall assignments. */
2490 static int
2491 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2493 gfc_ref *lref;
2494 gfc_ref *rref;
2495 int need_temp;
2496 gfc_symbol *lsym;
2498 lsym = c->expr1->symtree->n.sym;
2499 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2501 /* Now check for dependencies within the 'variable'
2502 expression itself. These are treated by making a complete
2503 copy of variable and changing all the references to it
2504 point to the copy instead. Note that the shallow copy of
2505 the variable will not suffice for derived types with
2506 pointer components. We therefore leave these to their
2507 own devices. */
2508 if (lsym->ts.type == BT_DERIVED
2509 && lsym->ts.u.derived->attr.pointer_comp)
2510 return need_temp;
2512 new_symtree = NULL;
2513 if (find_forall_index (c->expr1, lsym, 2) == SUCCESS)
2515 forall_make_variable_temp (c, pre, post);
2516 need_temp = 0;
2519 /* Substrings with dependencies are treated in the same
2520 way. */
2521 if (c->expr1->ts.type == BT_CHARACTER
2522 && c->expr1->ref
2523 && c->expr2->expr_type == EXPR_VARIABLE
2524 && lsym == c->expr2->symtree->n.sym)
2526 for (lref = c->expr1->ref; lref; lref = lref->next)
2527 if (lref->type == REF_SUBSTRING)
2528 break;
2529 for (rref = c->expr2->ref; rref; rref = rref->next)
2530 if (rref->type == REF_SUBSTRING)
2531 break;
2533 if (rref && lref
2534 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2536 forall_make_variable_temp (c, pre, post);
2537 need_temp = 0;
2540 return need_temp;
2544 static void
2545 cleanup_forall_symtrees (gfc_code *c)
2547 forall_restore_symtree (c->expr1);
2548 forall_restore_symtree (c->expr2);
2549 free (new_symtree->n.sym);
2550 free (new_symtree);
2554 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2555 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2556 indicates whether we should generate code to test the FORALLs mask
2557 array. OUTER is the loop header to be used for initializing mask
2558 indices.
2560 The generated loop format is:
2561 count = (end - start + step) / step
2562 loopvar = start
2563 while (1)
2565 if (count <=0 )
2566 goto end_of_loop
2567 <body>
2568 loopvar += step
2569 count --
2571 end_of_loop: */
2573 static tree
2574 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2575 int mask_flag, stmtblock_t *outer)
2577 int n, nvar;
2578 tree tmp;
2579 tree cond;
2580 stmtblock_t block;
2581 tree exit_label;
2582 tree count;
2583 tree var, start, end, step;
2584 iter_info *iter;
2586 /* Initialize the mask index outside the FORALL nest. */
2587 if (mask_flag && forall_tmp->mask)
2588 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2590 iter = forall_tmp->this_loop;
2591 nvar = forall_tmp->nvar;
2592 for (n = 0; n < nvar; n++)
2594 var = iter->var;
2595 start = iter->start;
2596 end = iter->end;
2597 step = iter->step;
2599 exit_label = gfc_build_label_decl (NULL_TREE);
2600 TREE_USED (exit_label) = 1;
2602 /* The loop counter. */
2603 count = gfc_create_var (TREE_TYPE (var), "count");
2605 /* The body of the loop. */
2606 gfc_init_block (&block);
2608 /* The exit condition. */
2609 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2610 count, build_int_cst (TREE_TYPE (count), 0));
2611 tmp = build1_v (GOTO_EXPR, exit_label);
2612 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2613 cond, tmp, build_empty_stmt (input_location));
2614 gfc_add_expr_to_block (&block, tmp);
2616 /* The main loop body. */
2617 gfc_add_expr_to_block (&block, body);
2619 /* Increment the loop variable. */
2620 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2621 step);
2622 gfc_add_modify (&block, var, tmp);
2624 /* Advance to the next mask element. Only do this for the
2625 innermost loop. */
2626 if (n == 0 && mask_flag && forall_tmp->mask)
2628 tree maskindex = forall_tmp->maskindex;
2629 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2630 maskindex, gfc_index_one_node);
2631 gfc_add_modify (&block, maskindex, tmp);
2634 /* Decrement the loop counter. */
2635 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2636 build_int_cst (TREE_TYPE (var), 1));
2637 gfc_add_modify (&block, count, tmp);
2639 body = gfc_finish_block (&block);
2641 /* Loop var initialization. */
2642 gfc_init_block (&block);
2643 gfc_add_modify (&block, var, start);
2646 /* Initialize the loop counter. */
2647 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2648 start);
2649 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2650 tmp);
2651 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2652 tmp, step);
2653 gfc_add_modify (&block, count, tmp);
2655 /* The loop expression. */
2656 tmp = build1_v (LOOP_EXPR, body);
2657 gfc_add_expr_to_block (&block, tmp);
2659 /* The exit label. */
2660 tmp = build1_v (LABEL_EXPR, exit_label);
2661 gfc_add_expr_to_block (&block, tmp);
2663 body = gfc_finish_block (&block);
2664 iter = iter->next;
2666 return body;
2670 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2671 is nonzero, the body is controlled by all masks in the forall nest.
2672 Otherwise, the innermost loop is not controlled by it's mask. This
2673 is used for initializing that mask. */
2675 static tree
2676 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2677 int mask_flag)
2679 tree tmp;
2680 stmtblock_t header;
2681 forall_info *forall_tmp;
2682 tree mask, maskindex;
2684 gfc_start_block (&header);
2686 forall_tmp = nested_forall_info;
2687 while (forall_tmp != NULL)
2689 /* Generate body with masks' control. */
2690 if (mask_flag)
2692 mask = forall_tmp->mask;
2693 maskindex = forall_tmp->maskindex;
2695 /* If a mask was specified make the assignment conditional. */
2696 if (mask)
2698 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2699 body = build3_v (COND_EXPR, tmp, body,
2700 build_empty_stmt (input_location));
2703 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2704 forall_tmp = forall_tmp->prev_nest;
2705 mask_flag = 1;
2708 gfc_add_expr_to_block (&header, body);
2709 return gfc_finish_block (&header);
2713 /* Allocate data for holding a temporary array. Returns either a local
2714 temporary array or a pointer variable. */
2716 static tree
2717 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2718 tree elem_type)
2720 tree tmpvar;
2721 tree type;
2722 tree tmp;
2724 if (INTEGER_CST_P (size))
2725 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2726 size, gfc_index_one_node);
2727 else
2728 tmp = NULL_TREE;
2730 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2731 type = build_array_type (elem_type, type);
2732 if (gfc_can_put_var_on_stack (bytesize))
2734 gcc_assert (INTEGER_CST_P (size));
2735 tmpvar = gfc_create_var (type, "temp");
2736 *pdata = NULL_TREE;
2738 else
2740 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2741 *pdata = convert (pvoid_type_node, tmpvar);
2743 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2744 gfc_add_modify (pblock, tmpvar, tmp);
2746 return tmpvar;
2750 /* Generate codes to copy the temporary to the actual lhs. */
2752 static tree
2753 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2754 tree count1, tree wheremask, bool invert)
2756 gfc_ss *lss;
2757 gfc_se lse, rse;
2758 stmtblock_t block, body;
2759 gfc_loopinfo loop1;
2760 tree tmp;
2761 tree wheremaskexpr;
2763 /* Walk the lhs. */
2764 lss = gfc_walk_expr (expr);
2766 if (lss == gfc_ss_terminator)
2768 gfc_start_block (&block);
2770 gfc_init_se (&lse, NULL);
2772 /* Translate the expression. */
2773 gfc_conv_expr (&lse, expr);
2775 /* Form the expression for the temporary. */
2776 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2778 /* Use the scalar assignment as is. */
2779 gfc_add_block_to_block (&block, &lse.pre);
2780 gfc_add_modify (&block, lse.expr, tmp);
2781 gfc_add_block_to_block (&block, &lse.post);
2783 /* Increment the count1. */
2784 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2785 count1, gfc_index_one_node);
2786 gfc_add_modify (&block, count1, tmp);
2788 tmp = gfc_finish_block (&block);
2790 else
2792 gfc_start_block (&block);
2794 gfc_init_loopinfo (&loop1);
2795 gfc_init_se (&rse, NULL);
2796 gfc_init_se (&lse, NULL);
2798 /* Associate the lss with the loop. */
2799 gfc_add_ss_to_loop (&loop1, lss);
2801 /* Calculate the bounds of the scalarization. */
2802 gfc_conv_ss_startstride (&loop1);
2803 /* Setup the scalarizing loops. */
2804 gfc_conv_loop_setup (&loop1, &expr->where);
2806 gfc_mark_ss_chain_used (lss, 1);
2808 /* Start the scalarized loop body. */
2809 gfc_start_scalarized_body (&loop1, &body);
2811 /* Setup the gfc_se structures. */
2812 gfc_copy_loopinfo_to_se (&lse, &loop1);
2813 lse.ss = lss;
2815 /* Form the expression of the temporary. */
2816 if (lss != gfc_ss_terminator)
2817 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2818 /* Translate expr. */
2819 gfc_conv_expr (&lse, expr);
2821 /* Use the scalar assignment. */
2822 rse.string_length = lse.string_length;
2823 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
2825 /* Form the mask expression according to the mask tree list. */
2826 if (wheremask)
2828 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2829 if (invert)
2830 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2831 TREE_TYPE (wheremaskexpr),
2832 wheremaskexpr);
2833 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2834 wheremaskexpr, tmp,
2835 build_empty_stmt (input_location));
2838 gfc_add_expr_to_block (&body, tmp);
2840 /* Increment count1. */
2841 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2842 count1, gfc_index_one_node);
2843 gfc_add_modify (&body, count1, tmp);
2845 /* Increment count3. */
2846 if (count3)
2848 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2849 gfc_array_index_type, count3,
2850 gfc_index_one_node);
2851 gfc_add_modify (&body, count3, tmp);
2854 /* Generate the copying loops. */
2855 gfc_trans_scalarizing_loops (&loop1, &body);
2856 gfc_add_block_to_block (&block, &loop1.pre);
2857 gfc_add_block_to_block (&block, &loop1.post);
2858 gfc_cleanup_loop (&loop1);
2860 tmp = gfc_finish_block (&block);
2862 return tmp;
2866 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
2867 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
2868 and should not be freed. WHEREMASK is the conditional execution mask
2869 whose sense may be inverted by INVERT. */
2871 static tree
2872 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
2873 tree count1, gfc_ss *lss, gfc_ss *rss,
2874 tree wheremask, bool invert)
2876 stmtblock_t block, body1;
2877 gfc_loopinfo loop;
2878 gfc_se lse;
2879 gfc_se rse;
2880 tree tmp;
2881 tree wheremaskexpr;
2883 gfc_start_block (&block);
2885 gfc_init_se (&rse, NULL);
2886 gfc_init_se (&lse, NULL);
2888 if (lss == gfc_ss_terminator)
2890 gfc_init_block (&body1);
2891 gfc_conv_expr (&rse, expr2);
2892 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2894 else
2896 /* Initialize the loop. */
2897 gfc_init_loopinfo (&loop);
2899 /* We may need LSS to determine the shape of the expression. */
2900 gfc_add_ss_to_loop (&loop, lss);
2901 gfc_add_ss_to_loop (&loop, rss);
2903 gfc_conv_ss_startstride (&loop);
2904 gfc_conv_loop_setup (&loop, &expr2->where);
2906 gfc_mark_ss_chain_used (rss, 1);
2907 /* Start the loop body. */
2908 gfc_start_scalarized_body (&loop, &body1);
2910 /* Translate the expression. */
2911 gfc_copy_loopinfo_to_se (&rse, &loop);
2912 rse.ss = rss;
2913 gfc_conv_expr (&rse, expr2);
2915 /* Form the expression of the temporary. */
2916 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2919 /* Use the scalar assignment. */
2920 lse.string_length = rse.string_length;
2921 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
2922 expr2->expr_type == EXPR_VARIABLE, true);
2924 /* Form the mask expression according to the mask tree list. */
2925 if (wheremask)
2927 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2928 if (invert)
2929 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2930 TREE_TYPE (wheremaskexpr),
2931 wheremaskexpr);
2932 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2933 wheremaskexpr, tmp,
2934 build_empty_stmt (input_location));
2937 gfc_add_expr_to_block (&body1, tmp);
2939 if (lss == gfc_ss_terminator)
2941 gfc_add_block_to_block (&block, &body1);
2943 /* Increment count1. */
2944 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2945 count1, gfc_index_one_node);
2946 gfc_add_modify (&block, count1, tmp);
2948 else
2950 /* Increment count1. */
2951 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2952 count1, gfc_index_one_node);
2953 gfc_add_modify (&body1, count1, tmp);
2955 /* Increment count3. */
2956 if (count3)
2958 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2959 gfc_array_index_type,
2960 count3, gfc_index_one_node);
2961 gfc_add_modify (&body1, count3, tmp);
2964 /* Generate the copying loops. */
2965 gfc_trans_scalarizing_loops (&loop, &body1);
2967 gfc_add_block_to_block (&block, &loop.pre);
2968 gfc_add_block_to_block (&block, &loop.post);
2970 gfc_cleanup_loop (&loop);
2971 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
2972 as tree nodes in SS may not be valid in different scope. */
2975 tmp = gfc_finish_block (&block);
2976 return tmp;
2980 /* Calculate the size of temporary needed in the assignment inside forall.
2981 LSS and RSS are filled in this function. */
2983 static tree
2984 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
2985 stmtblock_t * pblock,
2986 gfc_ss **lss, gfc_ss **rss)
2988 gfc_loopinfo loop;
2989 tree size;
2990 int i;
2991 int save_flag;
2992 tree tmp;
2994 *lss = gfc_walk_expr (expr1);
2995 *rss = NULL;
2997 size = gfc_index_one_node;
2998 if (*lss != gfc_ss_terminator)
3000 gfc_init_loopinfo (&loop);
3002 /* Walk the RHS of the expression. */
3003 *rss = gfc_walk_expr (expr2);
3004 if (*rss == gfc_ss_terminator)
3005 /* The rhs is scalar. Add a ss for the expression. */
3006 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3008 /* Associate the SS with the loop. */
3009 gfc_add_ss_to_loop (&loop, *lss);
3010 /* We don't actually need to add the rhs at this point, but it might
3011 make guessing the loop bounds a bit easier. */
3012 gfc_add_ss_to_loop (&loop, *rss);
3014 /* We only want the shape of the expression, not rest of the junk
3015 generated by the scalarizer. */
3016 loop.array_parameter = 1;
3018 /* Calculate the bounds of the scalarization. */
3019 save_flag = gfc_option.rtcheck;
3020 gfc_option.rtcheck &= !GFC_RTCHECK_BOUNDS;
3021 gfc_conv_ss_startstride (&loop);
3022 gfc_option.rtcheck = save_flag;
3023 gfc_conv_loop_setup (&loop, &expr2->where);
3025 /* Figure out how many elements we need. */
3026 for (i = 0; i < loop.dimen; i++)
3028 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3029 gfc_array_index_type,
3030 gfc_index_one_node, loop.from[i]);
3031 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3032 gfc_array_index_type, tmp, loop.to[i]);
3033 size = fold_build2_loc (input_location, MULT_EXPR,
3034 gfc_array_index_type, size, tmp);
3036 gfc_add_block_to_block (pblock, &loop.pre);
3037 size = gfc_evaluate_now (size, pblock);
3038 gfc_add_block_to_block (pblock, &loop.post);
3040 /* TODO: write a function that cleans up a loopinfo without freeing
3041 the SS chains. Currently a NOP. */
3044 return size;
3048 /* Calculate the overall iterator number of the nested forall construct.
3049 This routine actually calculates the number of times the body of the
3050 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3051 that by the expression INNER_SIZE. The BLOCK argument specifies the
3052 block in which to calculate the result, and the optional INNER_SIZE_BODY
3053 argument contains any statements that need to executed (inside the loop)
3054 to initialize or calculate INNER_SIZE. */
3056 static tree
3057 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3058 stmtblock_t *inner_size_body, stmtblock_t *block)
3060 forall_info *forall_tmp = nested_forall_info;
3061 tree tmp, number;
3062 stmtblock_t body;
3064 /* We can eliminate the innermost unconditional loops with constant
3065 array bounds. */
3066 if (INTEGER_CST_P (inner_size))
3068 while (forall_tmp
3069 && !forall_tmp->mask
3070 && INTEGER_CST_P (forall_tmp->size))
3072 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3073 gfc_array_index_type,
3074 inner_size, forall_tmp->size);
3075 forall_tmp = forall_tmp->prev_nest;
3078 /* If there are no loops left, we have our constant result. */
3079 if (!forall_tmp)
3080 return inner_size;
3083 /* Otherwise, create a temporary variable to compute the result. */
3084 number = gfc_create_var (gfc_array_index_type, "num");
3085 gfc_add_modify (block, number, gfc_index_zero_node);
3087 gfc_start_block (&body);
3088 if (inner_size_body)
3089 gfc_add_block_to_block (&body, inner_size_body);
3090 if (forall_tmp)
3091 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3092 gfc_array_index_type, number, inner_size);
3093 else
3094 tmp = inner_size;
3095 gfc_add_modify (&body, number, tmp);
3096 tmp = gfc_finish_block (&body);
3098 /* Generate loops. */
3099 if (forall_tmp != NULL)
3100 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3102 gfc_add_expr_to_block (block, tmp);
3104 return number;
3108 /* Allocate temporary for forall construct. SIZE is the size of temporary
3109 needed. PTEMP1 is returned for space free. */
3111 static tree
3112 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3113 tree * ptemp1)
3115 tree bytesize;
3116 tree unit;
3117 tree tmp;
3119 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3120 if (!integer_onep (unit))
3121 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3122 gfc_array_index_type, size, unit);
3123 else
3124 bytesize = size;
3126 *ptemp1 = NULL;
3127 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3129 if (*ptemp1)
3130 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3131 return tmp;
3135 /* Allocate temporary for forall construct according to the information in
3136 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3137 assignment inside forall. PTEMP1 is returned for space free. */
3139 static tree
3140 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3141 tree inner_size, stmtblock_t * inner_size_body,
3142 stmtblock_t * block, tree * ptemp1)
3144 tree size;
3146 /* Calculate the total size of temporary needed in forall construct. */
3147 size = compute_overall_iter_number (nested_forall_info, inner_size,
3148 inner_size_body, block);
3150 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3154 /* Handle assignments inside forall which need temporary.
3156 forall (i=start:end:stride; maskexpr)
3157 e<i> = f<i>
3158 end forall
3159 (where e,f<i> are arbitrary expressions possibly involving i
3160 and there is a dependency between e<i> and f<i>)
3161 Translates to:
3162 masktmp(:) = maskexpr(:)
3164 maskindex = 0;
3165 count1 = 0;
3166 num = 0;
3167 for (i = start; i <= end; i += stride)
3168 num += SIZE (f<i>)
3169 count1 = 0;
3170 ALLOCATE (tmp(num))
3171 for (i = start; i <= end; i += stride)
3173 if (masktmp[maskindex++])
3174 tmp[count1++] = f<i>
3176 maskindex = 0;
3177 count1 = 0;
3178 for (i = start; i <= end; i += stride)
3180 if (masktmp[maskindex++])
3181 e<i> = tmp[count1++]
3183 DEALLOCATE (tmp)
3185 static void
3186 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3187 tree wheremask, bool invert,
3188 forall_info * nested_forall_info,
3189 stmtblock_t * block)
3191 tree type;
3192 tree inner_size;
3193 gfc_ss *lss, *rss;
3194 tree count, count1;
3195 tree tmp, tmp1;
3196 tree ptemp1;
3197 stmtblock_t inner_size_body;
3199 /* Create vars. count1 is the current iterator number of the nested
3200 forall. */
3201 count1 = gfc_create_var (gfc_array_index_type, "count1");
3203 /* Count is the wheremask index. */
3204 if (wheremask)
3206 count = gfc_create_var (gfc_array_index_type, "count");
3207 gfc_add_modify (block, count, gfc_index_zero_node);
3209 else
3210 count = NULL;
3212 /* Initialize count1. */
3213 gfc_add_modify (block, count1, gfc_index_zero_node);
3215 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3216 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3217 gfc_init_block (&inner_size_body);
3218 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3219 &lss, &rss);
3221 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3222 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3224 if (!expr1->ts.u.cl->backend_decl)
3226 gfc_se tse;
3227 gfc_init_se (&tse, NULL);
3228 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3229 expr1->ts.u.cl->backend_decl = tse.expr;
3231 type = gfc_get_character_type_len (gfc_default_character_kind,
3232 expr1->ts.u.cl->backend_decl);
3234 else
3235 type = gfc_typenode_for_spec (&expr1->ts);
3237 /* Allocate temporary for nested forall construct according to the
3238 information in nested_forall_info and inner_size. */
3239 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3240 &inner_size_body, block, &ptemp1);
3242 /* Generate codes to copy rhs to the temporary . */
3243 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3244 wheremask, invert);
3246 /* Generate body and loops according to the information in
3247 nested_forall_info. */
3248 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3249 gfc_add_expr_to_block (block, tmp);
3251 /* Reset count1. */
3252 gfc_add_modify (block, count1, gfc_index_zero_node);
3254 /* Reset count. */
3255 if (wheremask)
3256 gfc_add_modify (block, count, gfc_index_zero_node);
3258 /* Generate codes to copy the temporary to lhs. */
3259 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3260 wheremask, invert);
3262 /* Generate body and loops according to the information in
3263 nested_forall_info. */
3264 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3265 gfc_add_expr_to_block (block, tmp);
3267 if (ptemp1)
3269 /* Free the temporary. */
3270 tmp = gfc_call_free (ptemp1);
3271 gfc_add_expr_to_block (block, tmp);
3276 /* Translate pointer assignment inside FORALL which need temporary. */
3278 static void
3279 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3280 forall_info * nested_forall_info,
3281 stmtblock_t * block)
3283 tree type;
3284 tree inner_size;
3285 gfc_ss *lss, *rss;
3286 gfc_se lse;
3287 gfc_se rse;
3288 gfc_array_info *info;
3289 gfc_loopinfo loop;
3290 tree desc;
3291 tree parm;
3292 tree parmtype;
3293 stmtblock_t body;
3294 tree count;
3295 tree tmp, tmp1, ptemp1;
3297 count = gfc_create_var (gfc_array_index_type, "count");
3298 gfc_add_modify (block, count, gfc_index_zero_node);
3300 inner_size = gfc_index_one_node;
3301 lss = gfc_walk_expr (expr1);
3302 rss = gfc_walk_expr (expr2);
3303 if (lss == gfc_ss_terminator)
3305 type = gfc_typenode_for_spec (&expr1->ts);
3306 type = build_pointer_type (type);
3308 /* Allocate temporary for nested forall construct according to the
3309 information in nested_forall_info and inner_size. */
3310 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3311 inner_size, NULL, block, &ptemp1);
3312 gfc_start_block (&body);
3313 gfc_init_se (&lse, NULL);
3314 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3315 gfc_init_se (&rse, NULL);
3316 rse.want_pointer = 1;
3317 gfc_conv_expr (&rse, expr2);
3318 gfc_add_block_to_block (&body, &rse.pre);
3319 gfc_add_modify (&body, lse.expr,
3320 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3321 gfc_add_block_to_block (&body, &rse.post);
3323 /* Increment count. */
3324 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3325 count, gfc_index_one_node);
3326 gfc_add_modify (&body, count, tmp);
3328 tmp = gfc_finish_block (&body);
3330 /* Generate body and loops according to the information in
3331 nested_forall_info. */
3332 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3333 gfc_add_expr_to_block (block, tmp);
3335 /* Reset count. */
3336 gfc_add_modify (block, count, gfc_index_zero_node);
3338 gfc_start_block (&body);
3339 gfc_init_se (&lse, NULL);
3340 gfc_init_se (&rse, NULL);
3341 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3342 lse.want_pointer = 1;
3343 gfc_conv_expr (&lse, expr1);
3344 gfc_add_block_to_block (&body, &lse.pre);
3345 gfc_add_modify (&body, lse.expr, rse.expr);
3346 gfc_add_block_to_block (&body, &lse.post);
3347 /* Increment count. */
3348 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3349 count, gfc_index_one_node);
3350 gfc_add_modify (&body, count, tmp);
3351 tmp = gfc_finish_block (&body);
3353 /* Generate body and loops according to the information in
3354 nested_forall_info. */
3355 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3356 gfc_add_expr_to_block (block, tmp);
3358 else
3360 gfc_init_loopinfo (&loop);
3362 /* Associate the SS with the loop. */
3363 gfc_add_ss_to_loop (&loop, rss);
3365 /* Setup the scalarizing loops and bounds. */
3366 gfc_conv_ss_startstride (&loop);
3368 gfc_conv_loop_setup (&loop, &expr2->where);
3370 info = &rss->info->data.array;
3371 desc = info->descriptor;
3373 /* Make a new descriptor. */
3374 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3375 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3376 loop.from, loop.to, 1,
3377 GFC_ARRAY_UNKNOWN, true);
3379 /* Allocate temporary for nested forall construct. */
3380 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3381 inner_size, NULL, block, &ptemp1);
3382 gfc_start_block (&body);
3383 gfc_init_se (&lse, NULL);
3384 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3385 lse.direct_byref = 1;
3386 rss = gfc_walk_expr (expr2);
3387 gfc_conv_expr_descriptor (&lse, expr2, rss);
3389 gfc_add_block_to_block (&body, &lse.pre);
3390 gfc_add_block_to_block (&body, &lse.post);
3392 /* Increment count. */
3393 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3394 count, gfc_index_one_node);
3395 gfc_add_modify (&body, count, tmp);
3397 tmp = gfc_finish_block (&body);
3399 /* Generate body and loops according to the information in
3400 nested_forall_info. */
3401 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3402 gfc_add_expr_to_block (block, tmp);
3404 /* Reset count. */
3405 gfc_add_modify (block, count, gfc_index_zero_node);
3407 parm = gfc_build_array_ref (tmp1, count, NULL);
3408 lss = gfc_walk_expr (expr1);
3409 gfc_init_se (&lse, NULL);
3410 gfc_conv_expr_descriptor (&lse, expr1, lss);
3411 gfc_add_modify (&lse.pre, lse.expr, parm);
3412 gfc_start_block (&body);
3413 gfc_add_block_to_block (&body, &lse.pre);
3414 gfc_add_block_to_block (&body, &lse.post);
3416 /* Increment count. */
3417 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3418 count, gfc_index_one_node);
3419 gfc_add_modify (&body, count, tmp);
3421 tmp = gfc_finish_block (&body);
3423 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3424 gfc_add_expr_to_block (block, tmp);
3426 /* Free the temporary. */
3427 if (ptemp1)
3429 tmp = gfc_call_free (ptemp1);
3430 gfc_add_expr_to_block (block, tmp);
3435 /* FORALL and WHERE statements are really nasty, especially when you nest
3436 them. All the rhs of a forall assignment must be evaluated before the
3437 actual assignments are performed. Presumably this also applies to all the
3438 assignments in an inner where statement. */
3440 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3441 linear array, relying on the fact that we process in the same order in all
3442 loops.
3444 forall (i=start:end:stride; maskexpr)
3445 e<i> = f<i>
3446 g<i> = h<i>
3447 end forall
3448 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3449 Translates to:
3450 count = ((end + 1 - start) / stride)
3451 masktmp(:) = maskexpr(:)
3453 maskindex = 0;
3454 for (i = start; i <= end; i += stride)
3456 if (masktmp[maskindex++])
3457 e<i> = f<i>
3459 maskindex = 0;
3460 for (i = start; i <= end; i += stride)
3462 if (masktmp[maskindex++])
3463 g<i> = h<i>
3466 Note that this code only works when there are no dependencies.
3467 Forall loop with array assignments and data dependencies are a real pain,
3468 because the size of the temporary cannot always be determined before the
3469 loop is executed. This problem is compounded by the presence of nested
3470 FORALL constructs.
3473 static tree
3474 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3476 stmtblock_t pre;
3477 stmtblock_t post;
3478 stmtblock_t block;
3479 stmtblock_t body;
3480 tree *var;
3481 tree *start;
3482 tree *end;
3483 tree *step;
3484 gfc_expr **varexpr;
3485 tree tmp;
3486 tree assign;
3487 tree size;
3488 tree maskindex;
3489 tree mask;
3490 tree pmask;
3491 tree cycle_label = NULL_TREE;
3492 int n;
3493 int nvar;
3494 int need_temp;
3495 gfc_forall_iterator *fa;
3496 gfc_se se;
3497 gfc_code *c;
3498 gfc_saved_var *saved_vars;
3499 iter_info *this_forall;
3500 forall_info *info;
3501 bool need_mask;
3503 /* Do nothing if the mask is false. */
3504 if (code->expr1
3505 && code->expr1->expr_type == EXPR_CONSTANT
3506 && !code->expr1->value.logical)
3507 return build_empty_stmt (input_location);
3509 n = 0;
3510 /* Count the FORALL index number. */
3511 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3512 n++;
3513 nvar = n;
3515 /* Allocate the space for var, start, end, step, varexpr. */
3516 var = XCNEWVEC (tree, nvar);
3517 start = XCNEWVEC (tree, nvar);
3518 end = XCNEWVEC (tree, nvar);
3519 step = XCNEWVEC (tree, nvar);
3520 varexpr = XCNEWVEC (gfc_expr *, nvar);
3521 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3523 /* Allocate the space for info. */
3524 info = XCNEW (forall_info);
3526 gfc_start_block (&pre);
3527 gfc_init_block (&post);
3528 gfc_init_block (&block);
3530 n = 0;
3531 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3533 gfc_symbol *sym = fa->var->symtree->n.sym;
3535 /* Allocate space for this_forall. */
3536 this_forall = XCNEW (iter_info);
3538 /* Create a temporary variable for the FORALL index. */
3539 tmp = gfc_typenode_for_spec (&sym->ts);
3540 var[n] = gfc_create_var (tmp, sym->name);
3541 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3543 /* Record it in this_forall. */
3544 this_forall->var = var[n];
3546 /* Replace the index symbol's backend_decl with the temporary decl. */
3547 sym->backend_decl = var[n];
3549 /* Work out the start, end and stride for the loop. */
3550 gfc_init_se (&se, NULL);
3551 gfc_conv_expr_val (&se, fa->start);
3552 /* Record it in this_forall. */
3553 this_forall->start = se.expr;
3554 gfc_add_block_to_block (&block, &se.pre);
3555 start[n] = se.expr;
3557 gfc_init_se (&se, NULL);
3558 gfc_conv_expr_val (&se, fa->end);
3559 /* Record it in this_forall. */
3560 this_forall->end = se.expr;
3561 gfc_make_safe_expr (&se);
3562 gfc_add_block_to_block (&block, &se.pre);
3563 end[n] = se.expr;
3565 gfc_init_se (&se, NULL);
3566 gfc_conv_expr_val (&se, fa->stride);
3567 /* Record it in this_forall. */
3568 this_forall->step = se.expr;
3569 gfc_make_safe_expr (&se);
3570 gfc_add_block_to_block (&block, &se.pre);
3571 step[n] = se.expr;
3573 /* Set the NEXT field of this_forall to NULL. */
3574 this_forall->next = NULL;
3575 /* Link this_forall to the info construct. */
3576 if (info->this_loop)
3578 iter_info *iter_tmp = info->this_loop;
3579 while (iter_tmp->next != NULL)
3580 iter_tmp = iter_tmp->next;
3581 iter_tmp->next = this_forall;
3583 else
3584 info->this_loop = this_forall;
3586 n++;
3588 nvar = n;
3590 /* Calculate the size needed for the current forall level. */
3591 size = gfc_index_one_node;
3592 for (n = 0; n < nvar; n++)
3594 /* size = (end + step - start) / step. */
3595 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3596 step[n], start[n]);
3597 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3598 end[n], tmp);
3599 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3600 tmp, step[n]);
3601 tmp = convert (gfc_array_index_type, tmp);
3603 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3604 size, tmp);
3607 /* Record the nvar and size of current forall level. */
3608 info->nvar = nvar;
3609 info->size = size;
3611 if (code->expr1)
3613 /* If the mask is .true., consider the FORALL unconditional. */
3614 if (code->expr1->expr_type == EXPR_CONSTANT
3615 && code->expr1->value.logical)
3616 need_mask = false;
3617 else
3618 need_mask = true;
3620 else
3621 need_mask = false;
3623 /* First we need to allocate the mask. */
3624 if (need_mask)
3626 /* As the mask array can be very big, prefer compact boolean types. */
3627 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3628 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3629 size, NULL, &block, &pmask);
3630 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3632 /* Record them in the info structure. */
3633 info->maskindex = maskindex;
3634 info->mask = mask;
3636 else
3638 /* No mask was specified. */
3639 maskindex = NULL_TREE;
3640 mask = pmask = NULL_TREE;
3643 /* Link the current forall level to nested_forall_info. */
3644 info->prev_nest = nested_forall_info;
3645 nested_forall_info = info;
3647 /* Copy the mask into a temporary variable if required.
3648 For now we assume a mask temporary is needed. */
3649 if (need_mask)
3651 /* As the mask array can be very big, prefer compact boolean types. */
3652 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3654 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3656 /* Start of mask assignment loop body. */
3657 gfc_start_block (&body);
3659 /* Evaluate the mask expression. */
3660 gfc_init_se (&se, NULL);
3661 gfc_conv_expr_val (&se, code->expr1);
3662 gfc_add_block_to_block (&body, &se.pre);
3664 /* Store the mask. */
3665 se.expr = convert (mask_type, se.expr);
3667 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3668 gfc_add_modify (&body, tmp, se.expr);
3670 /* Advance to the next mask element. */
3671 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3672 maskindex, gfc_index_one_node);
3673 gfc_add_modify (&body, maskindex, tmp);
3675 /* Generate the loops. */
3676 tmp = gfc_finish_block (&body);
3677 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3678 gfc_add_expr_to_block (&block, tmp);
3681 if (code->op == EXEC_DO_CONCURRENT)
3683 gfc_init_block (&body);
3684 cycle_label = gfc_build_label_decl (NULL_TREE);
3685 code->cycle_label = cycle_label;
3686 tmp = gfc_trans_code (code->block->next);
3687 gfc_add_expr_to_block (&body, tmp);
3689 if (TREE_USED (cycle_label))
3691 tmp = build1_v (LABEL_EXPR, cycle_label);
3692 gfc_add_expr_to_block (&body, tmp);
3695 tmp = gfc_finish_block (&body);
3696 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3697 gfc_add_expr_to_block (&block, tmp);
3698 goto done;
3701 c = code->block->next;
3703 /* TODO: loop merging in FORALL statements. */
3704 /* Now that we've got a copy of the mask, generate the assignment loops. */
3705 while (c)
3707 switch (c->op)
3709 case EXEC_ASSIGN:
3710 /* A scalar or array assignment. DO the simple check for
3711 lhs to rhs dependencies. These make a temporary for the
3712 rhs and form a second forall block to copy to variable. */
3713 need_temp = check_forall_dependencies(c, &pre, &post);
3715 /* Temporaries due to array assignment data dependencies introduce
3716 no end of problems. */
3717 if (need_temp)
3718 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3719 nested_forall_info, &block);
3720 else
3722 /* Use the normal assignment copying routines. */
3723 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3725 /* Generate body and loops. */
3726 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3727 assign, 1);
3728 gfc_add_expr_to_block (&block, tmp);
3731 /* Cleanup any temporary symtrees that have been made to deal
3732 with dependencies. */
3733 if (new_symtree)
3734 cleanup_forall_symtrees (c);
3736 break;
3738 case EXEC_WHERE:
3739 /* Translate WHERE or WHERE construct nested in FORALL. */
3740 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3741 break;
3743 /* Pointer assignment inside FORALL. */
3744 case EXEC_POINTER_ASSIGN:
3745 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3746 if (need_temp)
3747 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3748 nested_forall_info, &block);
3749 else
3751 /* Use the normal assignment copying routines. */
3752 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3754 /* Generate body and loops. */
3755 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3756 assign, 1);
3757 gfc_add_expr_to_block (&block, tmp);
3759 break;
3761 case EXEC_FORALL:
3762 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3763 gfc_add_expr_to_block (&block, tmp);
3764 break;
3766 /* Explicit subroutine calls are prevented by the frontend but interface
3767 assignments can legitimately produce them. */
3768 case EXEC_ASSIGN_CALL:
3769 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3770 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3771 gfc_add_expr_to_block (&block, tmp);
3772 break;
3774 default:
3775 gcc_unreachable ();
3778 c = c->next;
3781 done:
3782 /* Restore the original index variables. */
3783 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3784 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3786 /* Free the space for var, start, end, step, varexpr. */
3787 free (var);
3788 free (start);
3789 free (end);
3790 free (step);
3791 free (varexpr);
3792 free (saved_vars);
3794 for (this_forall = info->this_loop; this_forall;)
3796 iter_info *next = this_forall->next;
3797 free (this_forall);
3798 this_forall = next;
3801 /* Free the space for this forall_info. */
3802 free (info);
3804 if (pmask)
3806 /* Free the temporary for the mask. */
3807 tmp = gfc_call_free (pmask);
3808 gfc_add_expr_to_block (&block, tmp);
3810 if (maskindex)
3811 pushdecl (maskindex);
3813 gfc_add_block_to_block (&pre, &block);
3814 gfc_add_block_to_block (&pre, &post);
3816 return gfc_finish_block (&pre);
3820 /* Translate the FORALL statement or construct. */
3822 tree gfc_trans_forall (gfc_code * code)
3824 return gfc_trans_forall_1 (code, NULL);
3828 /* Translate the DO CONCURRENT construct. */
3830 tree gfc_trans_do_concurrent (gfc_code * code)
3832 return gfc_trans_forall_1 (code, NULL);
3836 /* Evaluate the WHERE mask expression, copy its value to a temporary.
3837 If the WHERE construct is nested in FORALL, compute the overall temporary
3838 needed by the WHERE mask expression multiplied by the iterator number of
3839 the nested forall.
3840 ME is the WHERE mask expression.
3841 MASK is the current execution mask upon input, whose sense may or may
3842 not be inverted as specified by the INVERT argument.
3843 CMASK is the updated execution mask on output, or NULL if not required.
3844 PMASK is the pending execution mask on output, or NULL if not required.
3845 BLOCK is the block in which to place the condition evaluation loops. */
3847 static void
3848 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
3849 tree mask, bool invert, tree cmask, tree pmask,
3850 tree mask_type, stmtblock_t * block)
3852 tree tmp, tmp1;
3853 gfc_ss *lss, *rss;
3854 gfc_loopinfo loop;
3855 stmtblock_t body, body1;
3856 tree count, cond, mtmp;
3857 gfc_se lse, rse;
3859 gfc_init_loopinfo (&loop);
3861 lss = gfc_walk_expr (me);
3862 rss = gfc_walk_expr (me);
3864 /* Variable to index the temporary. */
3865 count = gfc_create_var (gfc_array_index_type, "count");
3866 /* Initialize count. */
3867 gfc_add_modify (block, count, gfc_index_zero_node);
3869 gfc_start_block (&body);
3871 gfc_init_se (&rse, NULL);
3872 gfc_init_se (&lse, NULL);
3874 if (lss == gfc_ss_terminator)
3876 gfc_init_block (&body1);
3878 else
3880 /* Initialize the loop. */
3881 gfc_init_loopinfo (&loop);
3883 /* We may need LSS to determine the shape of the expression. */
3884 gfc_add_ss_to_loop (&loop, lss);
3885 gfc_add_ss_to_loop (&loop, rss);
3887 gfc_conv_ss_startstride (&loop);
3888 gfc_conv_loop_setup (&loop, &me->where);
3890 gfc_mark_ss_chain_used (rss, 1);
3891 /* Start the loop body. */
3892 gfc_start_scalarized_body (&loop, &body1);
3894 /* Translate the expression. */
3895 gfc_copy_loopinfo_to_se (&rse, &loop);
3896 rse.ss = rss;
3897 gfc_conv_expr (&rse, me);
3900 /* Variable to evaluate mask condition. */
3901 cond = gfc_create_var (mask_type, "cond");
3902 if (mask && (cmask || pmask))
3903 mtmp = gfc_create_var (mask_type, "mask");
3904 else mtmp = NULL_TREE;
3906 gfc_add_block_to_block (&body1, &lse.pre);
3907 gfc_add_block_to_block (&body1, &rse.pre);
3909 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
3911 if (mask && (cmask || pmask))
3913 tmp = gfc_build_array_ref (mask, count, NULL);
3914 if (invert)
3915 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
3916 gfc_add_modify (&body1, mtmp, tmp);
3919 if (cmask)
3921 tmp1 = gfc_build_array_ref (cmask, count, NULL);
3922 tmp = cond;
3923 if (mask)
3924 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
3925 mtmp, tmp);
3926 gfc_add_modify (&body1, tmp1, tmp);
3929 if (pmask)
3931 tmp1 = gfc_build_array_ref (pmask, count, NULL);
3932 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
3933 if (mask)
3934 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
3935 tmp);
3936 gfc_add_modify (&body1, tmp1, tmp);
3939 gfc_add_block_to_block (&body1, &lse.post);
3940 gfc_add_block_to_block (&body1, &rse.post);
3942 if (lss == gfc_ss_terminator)
3944 gfc_add_block_to_block (&body, &body1);
3946 else
3948 /* Increment count. */
3949 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3950 count, gfc_index_one_node);
3951 gfc_add_modify (&body1, count, tmp1);
3953 /* Generate the copying loops. */
3954 gfc_trans_scalarizing_loops (&loop, &body1);
3956 gfc_add_block_to_block (&body, &loop.pre);
3957 gfc_add_block_to_block (&body, &loop.post);
3959 gfc_cleanup_loop (&loop);
3960 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3961 as tree nodes in SS may not be valid in different scope. */
3964 tmp1 = gfc_finish_block (&body);
3965 /* If the WHERE construct is inside FORALL, fill the full temporary. */
3966 if (nested_forall_info != NULL)
3967 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
3969 gfc_add_expr_to_block (block, tmp1);
3973 /* Translate an assignment statement in a WHERE statement or construct
3974 statement. The MASK expression is used to control which elements
3975 of EXPR1 shall be assigned. The sense of MASK is specified by
3976 INVERT. */
3978 static tree
3979 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
3980 tree mask, bool invert,
3981 tree count1, tree count2,
3982 gfc_code *cnext)
3984 gfc_se lse;
3985 gfc_se rse;
3986 gfc_ss *lss;
3987 gfc_ss *lss_section;
3988 gfc_ss *rss;
3990 gfc_loopinfo loop;
3991 tree tmp;
3992 stmtblock_t block;
3993 stmtblock_t body;
3994 tree index, maskexpr;
3996 /* A defined assignment. */
3997 if (cnext && cnext->resolved_sym)
3998 return gfc_trans_call (cnext, true, mask, count1, invert);
4000 #if 0
4001 /* TODO: handle this special case.
4002 Special case a single function returning an array. */
4003 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4005 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4006 if (tmp)
4007 return tmp;
4009 #endif
4011 /* Assignment of the form lhs = rhs. */
4012 gfc_start_block (&block);
4014 gfc_init_se (&lse, NULL);
4015 gfc_init_se (&rse, NULL);
4017 /* Walk the lhs. */
4018 lss = gfc_walk_expr (expr1);
4019 rss = NULL;
4021 /* In each where-assign-stmt, the mask-expr and the variable being
4022 defined shall be arrays of the same shape. */
4023 gcc_assert (lss != gfc_ss_terminator);
4025 /* The assignment needs scalarization. */
4026 lss_section = lss;
4028 /* Find a non-scalar SS from the lhs. */
4029 while (lss_section != gfc_ss_terminator
4030 && lss_section->info->type != GFC_SS_SECTION)
4031 lss_section = lss_section->next;
4033 gcc_assert (lss_section != gfc_ss_terminator);
4035 /* Initialize the scalarizer. */
4036 gfc_init_loopinfo (&loop);
4038 /* Walk the rhs. */
4039 rss = gfc_walk_expr (expr2);
4040 if (rss == gfc_ss_terminator)
4042 /* The rhs is scalar. Add a ss for the expression. */
4043 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4044 rss->info->where = 1;
4047 /* Associate the SS with the loop. */
4048 gfc_add_ss_to_loop (&loop, lss);
4049 gfc_add_ss_to_loop (&loop, rss);
4051 /* Calculate the bounds of the scalarization. */
4052 gfc_conv_ss_startstride (&loop);
4054 /* Resolve any data dependencies in the statement. */
4055 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4057 /* Setup the scalarizing loops. */
4058 gfc_conv_loop_setup (&loop, &expr2->where);
4060 /* Setup the gfc_se structures. */
4061 gfc_copy_loopinfo_to_se (&lse, &loop);
4062 gfc_copy_loopinfo_to_se (&rse, &loop);
4064 rse.ss = rss;
4065 gfc_mark_ss_chain_used (rss, 1);
4066 if (loop.temp_ss == NULL)
4068 lse.ss = lss;
4069 gfc_mark_ss_chain_used (lss, 1);
4071 else
4073 lse.ss = loop.temp_ss;
4074 gfc_mark_ss_chain_used (lss, 3);
4075 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4078 /* Start the scalarized loop body. */
4079 gfc_start_scalarized_body (&loop, &body);
4081 /* Translate the expression. */
4082 gfc_conv_expr (&rse, expr2);
4083 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4084 gfc_conv_tmp_array_ref (&lse);
4085 else
4086 gfc_conv_expr (&lse, expr1);
4088 /* Form the mask expression according to the mask. */
4089 index = count1;
4090 maskexpr = gfc_build_array_ref (mask, index, NULL);
4091 if (invert)
4092 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4093 TREE_TYPE (maskexpr), maskexpr);
4095 /* Use the scalar assignment as is. */
4096 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4097 loop.temp_ss != NULL, false, true);
4099 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4101 gfc_add_expr_to_block (&body, tmp);
4103 if (lss == gfc_ss_terminator)
4105 /* Increment count1. */
4106 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4107 count1, gfc_index_one_node);
4108 gfc_add_modify (&body, count1, tmp);
4110 /* Use the scalar assignment as is. */
4111 gfc_add_block_to_block (&block, &body);
4113 else
4115 gcc_assert (lse.ss == gfc_ss_terminator
4116 && rse.ss == gfc_ss_terminator);
4118 if (loop.temp_ss != NULL)
4120 /* Increment count1 before finish the main body of a scalarized
4121 expression. */
4122 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4123 gfc_array_index_type, count1, gfc_index_one_node);
4124 gfc_add_modify (&body, count1, tmp);
4125 gfc_trans_scalarized_loop_boundary (&loop, &body);
4127 /* We need to copy the temporary to the actual lhs. */
4128 gfc_init_se (&lse, NULL);
4129 gfc_init_se (&rse, NULL);
4130 gfc_copy_loopinfo_to_se (&lse, &loop);
4131 gfc_copy_loopinfo_to_se (&rse, &loop);
4133 rse.ss = loop.temp_ss;
4134 lse.ss = lss;
4136 gfc_conv_tmp_array_ref (&rse);
4137 gfc_conv_expr (&lse, expr1);
4139 gcc_assert (lse.ss == gfc_ss_terminator
4140 && rse.ss == gfc_ss_terminator);
4142 /* Form the mask expression according to the mask tree list. */
4143 index = count2;
4144 maskexpr = gfc_build_array_ref (mask, index, NULL);
4145 if (invert)
4146 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4147 TREE_TYPE (maskexpr), maskexpr);
4149 /* Use the scalar assignment as is. */
4150 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4151 true);
4152 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4153 build_empty_stmt (input_location));
4154 gfc_add_expr_to_block (&body, tmp);
4156 /* Increment count2. */
4157 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4158 gfc_array_index_type, count2,
4159 gfc_index_one_node);
4160 gfc_add_modify (&body, count2, tmp);
4162 else
4164 /* Increment count1. */
4165 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4166 gfc_array_index_type, count1,
4167 gfc_index_one_node);
4168 gfc_add_modify (&body, count1, tmp);
4171 /* Generate the copying loops. */
4172 gfc_trans_scalarizing_loops (&loop, &body);
4174 /* Wrap the whole thing up. */
4175 gfc_add_block_to_block (&block, &loop.pre);
4176 gfc_add_block_to_block (&block, &loop.post);
4177 gfc_cleanup_loop (&loop);
4180 return gfc_finish_block (&block);
4184 /* Translate the WHERE construct or statement.
4185 This function can be called iteratively to translate the nested WHERE
4186 construct or statement.
4187 MASK is the control mask. */
4189 static void
4190 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4191 forall_info * nested_forall_info, stmtblock_t * block)
4193 stmtblock_t inner_size_body;
4194 tree inner_size, size;
4195 gfc_ss *lss, *rss;
4196 tree mask_type;
4197 gfc_expr *expr1;
4198 gfc_expr *expr2;
4199 gfc_code *cblock;
4200 gfc_code *cnext;
4201 tree tmp;
4202 tree cond;
4203 tree count1, count2;
4204 bool need_cmask;
4205 bool need_pmask;
4206 int need_temp;
4207 tree pcmask = NULL_TREE;
4208 tree ppmask = NULL_TREE;
4209 tree cmask = NULL_TREE;
4210 tree pmask = NULL_TREE;
4211 gfc_actual_arglist *arg;
4213 /* the WHERE statement or the WHERE construct statement. */
4214 cblock = code->block;
4216 /* As the mask array can be very big, prefer compact boolean types. */
4217 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4219 /* Determine which temporary masks are needed. */
4220 if (!cblock->block)
4222 /* One clause: No ELSEWHEREs. */
4223 need_cmask = (cblock->next != 0);
4224 need_pmask = false;
4226 else if (cblock->block->block)
4228 /* Three or more clauses: Conditional ELSEWHEREs. */
4229 need_cmask = true;
4230 need_pmask = true;
4232 else if (cblock->next)
4234 /* Two clauses, the first non-empty. */
4235 need_cmask = true;
4236 need_pmask = (mask != NULL_TREE
4237 && cblock->block->next != 0);
4239 else if (!cblock->block->next)
4241 /* Two clauses, both empty. */
4242 need_cmask = false;
4243 need_pmask = false;
4245 /* Two clauses, the first empty, the second non-empty. */
4246 else if (mask)
4248 need_cmask = (cblock->block->expr1 != 0);
4249 need_pmask = true;
4251 else
4253 need_cmask = true;
4254 need_pmask = false;
4257 if (need_cmask || need_pmask)
4259 /* Calculate the size of temporary needed by the mask-expr. */
4260 gfc_init_block (&inner_size_body);
4261 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4262 &inner_size_body, &lss, &rss);
4264 gfc_free_ss_chain (lss);
4265 gfc_free_ss_chain (rss);
4267 /* Calculate the total size of temporary needed. */
4268 size = compute_overall_iter_number (nested_forall_info, inner_size,
4269 &inner_size_body, block);
4271 /* Check whether the size is negative. */
4272 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4273 gfc_index_zero_node);
4274 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4275 cond, gfc_index_zero_node, size);
4276 size = gfc_evaluate_now (size, block);
4278 /* Allocate temporary for WHERE mask if needed. */
4279 if (need_cmask)
4280 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4281 &pcmask);
4283 /* Allocate temporary for !mask if needed. */
4284 if (need_pmask)
4285 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4286 &ppmask);
4289 while (cblock)
4291 /* Each time around this loop, the where clause is conditional
4292 on the value of mask and invert, which are updated at the
4293 bottom of the loop. */
4295 /* Has mask-expr. */
4296 if (cblock->expr1)
4298 /* Ensure that the WHERE mask will be evaluated exactly once.
4299 If there are no statements in this WHERE/ELSEWHERE clause,
4300 then we don't need to update the control mask (cmask).
4301 If this is the last clause of the WHERE construct, then
4302 we don't need to update the pending control mask (pmask). */
4303 if (mask)
4304 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4305 mask, invert,
4306 cblock->next ? cmask : NULL_TREE,
4307 cblock->block ? pmask : NULL_TREE,
4308 mask_type, block);
4309 else
4310 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4311 NULL_TREE, false,
4312 (cblock->next || cblock->block)
4313 ? cmask : NULL_TREE,
4314 NULL_TREE, mask_type, block);
4316 invert = false;
4318 /* It's a final elsewhere-stmt. No mask-expr is present. */
4319 else
4320 cmask = mask;
4322 /* The body of this where clause are controlled by cmask with
4323 sense specified by invert. */
4325 /* Get the assignment statement of a WHERE statement, or the first
4326 statement in where-body-construct of a WHERE construct. */
4327 cnext = cblock->next;
4328 while (cnext)
4330 switch (cnext->op)
4332 /* WHERE assignment statement. */
4333 case EXEC_ASSIGN_CALL:
4335 arg = cnext->ext.actual;
4336 expr1 = expr2 = NULL;
4337 for (; arg; arg = arg->next)
4339 if (!arg->expr)
4340 continue;
4341 if (expr1 == NULL)
4342 expr1 = arg->expr;
4343 else
4344 expr2 = arg->expr;
4346 goto evaluate;
4348 case EXEC_ASSIGN:
4349 expr1 = cnext->expr1;
4350 expr2 = cnext->expr2;
4351 evaluate:
4352 if (nested_forall_info != NULL)
4354 need_temp = gfc_check_dependency (expr1, expr2, 0);
4355 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4356 gfc_trans_assign_need_temp (expr1, expr2,
4357 cmask, invert,
4358 nested_forall_info, block);
4359 else
4361 /* Variables to control maskexpr. */
4362 count1 = gfc_create_var (gfc_array_index_type, "count1");
4363 count2 = gfc_create_var (gfc_array_index_type, "count2");
4364 gfc_add_modify (block, count1, gfc_index_zero_node);
4365 gfc_add_modify (block, count2, gfc_index_zero_node);
4367 tmp = gfc_trans_where_assign (expr1, expr2,
4368 cmask, invert,
4369 count1, count2,
4370 cnext);
4372 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4373 tmp, 1);
4374 gfc_add_expr_to_block (block, tmp);
4377 else
4379 /* Variables to control maskexpr. */
4380 count1 = gfc_create_var (gfc_array_index_type, "count1");
4381 count2 = gfc_create_var (gfc_array_index_type, "count2");
4382 gfc_add_modify (block, count1, gfc_index_zero_node);
4383 gfc_add_modify (block, count2, gfc_index_zero_node);
4385 tmp = gfc_trans_where_assign (expr1, expr2,
4386 cmask, invert,
4387 count1, count2,
4388 cnext);
4389 gfc_add_expr_to_block (block, tmp);
4392 break;
4394 /* WHERE or WHERE construct is part of a where-body-construct. */
4395 case EXEC_WHERE:
4396 gfc_trans_where_2 (cnext, cmask, invert,
4397 nested_forall_info, block);
4398 break;
4400 default:
4401 gcc_unreachable ();
4404 /* The next statement within the same where-body-construct. */
4405 cnext = cnext->next;
4407 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4408 cblock = cblock->block;
4409 if (mask == NULL_TREE)
4411 /* If we're the initial WHERE, we can simply invert the sense
4412 of the current mask to obtain the "mask" for the remaining
4413 ELSEWHEREs. */
4414 invert = true;
4415 mask = cmask;
4417 else
4419 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4420 invert = false;
4421 mask = pmask;
4425 /* If we allocated a pending mask array, deallocate it now. */
4426 if (ppmask)
4428 tmp = gfc_call_free (ppmask);
4429 gfc_add_expr_to_block (block, tmp);
4432 /* If we allocated a current mask array, deallocate it now. */
4433 if (pcmask)
4435 tmp = gfc_call_free (pcmask);
4436 gfc_add_expr_to_block (block, tmp);
4440 /* Translate a simple WHERE construct or statement without dependencies.
4441 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4442 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4443 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4445 static tree
4446 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4448 stmtblock_t block, body;
4449 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4450 tree tmp, cexpr, tstmt, estmt;
4451 gfc_ss *css, *tdss, *tsss;
4452 gfc_se cse, tdse, tsse, edse, esse;
4453 gfc_loopinfo loop;
4454 gfc_ss *edss = 0;
4455 gfc_ss *esss = 0;
4457 /* Allow the scalarizer to workshare simple where loops. */
4458 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4459 ompws_flags |= OMPWS_SCALARIZER_WS;
4461 cond = cblock->expr1;
4462 tdst = cblock->next->expr1;
4463 tsrc = cblock->next->expr2;
4464 edst = eblock ? eblock->next->expr1 : NULL;
4465 esrc = eblock ? eblock->next->expr2 : NULL;
4467 gfc_start_block (&block);
4468 gfc_init_loopinfo (&loop);
4470 /* Handle the condition. */
4471 gfc_init_se (&cse, NULL);
4472 css = gfc_walk_expr (cond);
4473 gfc_add_ss_to_loop (&loop, css);
4475 /* Handle the then-clause. */
4476 gfc_init_se (&tdse, NULL);
4477 gfc_init_se (&tsse, NULL);
4478 tdss = gfc_walk_expr (tdst);
4479 tsss = gfc_walk_expr (tsrc);
4480 if (tsss == gfc_ss_terminator)
4482 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4483 tsss->info->where = 1;
4485 gfc_add_ss_to_loop (&loop, tdss);
4486 gfc_add_ss_to_loop (&loop, tsss);
4488 if (eblock)
4490 /* Handle the else clause. */
4491 gfc_init_se (&edse, NULL);
4492 gfc_init_se (&esse, NULL);
4493 edss = gfc_walk_expr (edst);
4494 esss = gfc_walk_expr (esrc);
4495 if (esss == gfc_ss_terminator)
4497 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4498 esss->info->where = 1;
4500 gfc_add_ss_to_loop (&loop, edss);
4501 gfc_add_ss_to_loop (&loop, esss);
4504 gfc_conv_ss_startstride (&loop);
4505 gfc_conv_loop_setup (&loop, &tdst->where);
4507 gfc_mark_ss_chain_used (css, 1);
4508 gfc_mark_ss_chain_used (tdss, 1);
4509 gfc_mark_ss_chain_used (tsss, 1);
4510 if (eblock)
4512 gfc_mark_ss_chain_used (edss, 1);
4513 gfc_mark_ss_chain_used (esss, 1);
4516 gfc_start_scalarized_body (&loop, &body);
4518 gfc_copy_loopinfo_to_se (&cse, &loop);
4519 gfc_copy_loopinfo_to_se (&tdse, &loop);
4520 gfc_copy_loopinfo_to_se (&tsse, &loop);
4521 cse.ss = css;
4522 tdse.ss = tdss;
4523 tsse.ss = tsss;
4524 if (eblock)
4526 gfc_copy_loopinfo_to_se (&edse, &loop);
4527 gfc_copy_loopinfo_to_se (&esse, &loop);
4528 edse.ss = edss;
4529 esse.ss = esss;
4532 gfc_conv_expr (&cse, cond);
4533 gfc_add_block_to_block (&body, &cse.pre);
4534 cexpr = cse.expr;
4536 gfc_conv_expr (&tsse, tsrc);
4537 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4538 gfc_conv_tmp_array_ref (&tdse);
4539 else
4540 gfc_conv_expr (&tdse, tdst);
4542 if (eblock)
4544 gfc_conv_expr (&esse, esrc);
4545 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4546 gfc_conv_tmp_array_ref (&edse);
4547 else
4548 gfc_conv_expr (&edse, edst);
4551 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4552 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4553 false, true)
4554 : build_empty_stmt (input_location);
4555 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4556 gfc_add_expr_to_block (&body, tmp);
4557 gfc_add_block_to_block (&body, &cse.post);
4559 gfc_trans_scalarizing_loops (&loop, &body);
4560 gfc_add_block_to_block (&block, &loop.pre);
4561 gfc_add_block_to_block (&block, &loop.post);
4562 gfc_cleanup_loop (&loop);
4564 return gfc_finish_block (&block);
4567 /* As the WHERE or WHERE construct statement can be nested, we call
4568 gfc_trans_where_2 to do the translation, and pass the initial
4569 NULL values for both the control mask and the pending control mask. */
4571 tree
4572 gfc_trans_where (gfc_code * code)
4574 stmtblock_t block;
4575 gfc_code *cblock;
4576 gfc_code *eblock;
4578 cblock = code->block;
4579 if (cblock->next
4580 && cblock->next->op == EXEC_ASSIGN
4581 && !cblock->next->next)
4583 eblock = cblock->block;
4584 if (!eblock)
4586 /* A simple "WHERE (cond) x = y" statement or block is
4587 dependence free if cond is not dependent upon writing x,
4588 and the source y is unaffected by the destination x. */
4589 if (!gfc_check_dependency (cblock->next->expr1,
4590 cblock->expr1, 0)
4591 && !gfc_check_dependency (cblock->next->expr1,
4592 cblock->next->expr2, 0))
4593 return gfc_trans_where_3 (cblock, NULL);
4595 else if (!eblock->expr1
4596 && !eblock->block
4597 && eblock->next
4598 && eblock->next->op == EXEC_ASSIGN
4599 && !eblock->next->next)
4601 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4602 block is dependence free if cond is not dependent on writes
4603 to x1 and x2, y1 is not dependent on writes to x2, and y2
4604 is not dependent on writes to x1, and both y's are not
4605 dependent upon their own x's. In addition to this, the
4606 final two dependency checks below exclude all but the same
4607 array reference if the where and elswhere destinations
4608 are the same. In short, this is VERY conservative and this
4609 is needed because the two loops, required by the standard
4610 are coalesced in gfc_trans_where_3. */
4611 if (!gfc_check_dependency(cblock->next->expr1,
4612 cblock->expr1, 0)
4613 && !gfc_check_dependency(eblock->next->expr1,
4614 cblock->expr1, 0)
4615 && !gfc_check_dependency(cblock->next->expr1,
4616 eblock->next->expr2, 1)
4617 && !gfc_check_dependency(eblock->next->expr1,
4618 cblock->next->expr2, 1)
4619 && !gfc_check_dependency(cblock->next->expr1,
4620 cblock->next->expr2, 1)
4621 && !gfc_check_dependency(eblock->next->expr1,
4622 eblock->next->expr2, 1)
4623 && !gfc_check_dependency(cblock->next->expr1,
4624 eblock->next->expr1, 0)
4625 && !gfc_check_dependency(eblock->next->expr1,
4626 cblock->next->expr1, 0))
4627 return gfc_trans_where_3 (cblock, eblock);
4631 gfc_start_block (&block);
4633 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4635 return gfc_finish_block (&block);
4639 /* CYCLE a DO loop. The label decl has already been created by
4640 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4641 node at the head of the loop. We must mark the label as used. */
4643 tree
4644 gfc_trans_cycle (gfc_code * code)
4646 tree cycle_label;
4648 cycle_label = code->ext.which_construct->cycle_label;
4649 gcc_assert (cycle_label);
4651 TREE_USED (cycle_label) = 1;
4652 return build1_v (GOTO_EXPR, cycle_label);
4656 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4657 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4658 loop. */
4660 tree
4661 gfc_trans_exit (gfc_code * code)
4663 tree exit_label;
4665 exit_label = code->ext.which_construct->exit_label;
4666 gcc_assert (exit_label);
4668 TREE_USED (exit_label) = 1;
4669 return build1_v (GOTO_EXPR, exit_label);
4673 /* Translate the ALLOCATE statement. */
4675 tree
4676 gfc_trans_allocate (gfc_code * code)
4678 gfc_alloc *al;
4679 gfc_expr *expr;
4680 gfc_se se;
4681 tree tmp;
4682 tree parm;
4683 tree stat;
4684 tree errmsg;
4685 tree errlen;
4686 tree label_errmsg;
4687 tree label_finish;
4688 tree memsz;
4689 tree expr3;
4690 tree slen3;
4691 stmtblock_t block;
4692 stmtblock_t post;
4693 gfc_expr *sz;
4694 gfc_se se_sz;
4696 if (!code->ext.alloc.list)
4697 return NULL_TREE;
4699 stat = tmp = memsz = NULL_TREE;
4700 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4702 gfc_init_block (&block);
4703 gfc_init_block (&post);
4705 /* STAT= (and maybe ERRMSG=) is present. */
4706 if (code->expr1)
4708 /* STAT=. */
4709 tree gfc_int4_type_node = gfc_get_int_type (4);
4710 stat = gfc_create_var (gfc_int4_type_node, "stat");
4712 /* ERRMSG= only makes sense with STAT=. */
4713 if (code->expr2)
4715 gfc_init_se (&se, NULL);
4716 gfc_conv_expr_lhs (&se, code->expr2);
4718 errlen = gfc_get_expr_charlen (code->expr2);
4719 errmsg = gfc_build_addr_expr (pchar_type_node, se.expr);
4721 else
4723 errmsg = null_pointer_node;
4724 errlen = build_int_cst (gfc_charlen_type_node, 0);
4727 /* GOTO destinations. */
4728 label_errmsg = gfc_build_label_decl (NULL_TREE);
4729 label_finish = gfc_build_label_decl (NULL_TREE);
4730 TREE_USED (label_errmsg) = 1;
4731 TREE_USED (label_finish) = 1;
4734 expr3 = NULL_TREE;
4735 slen3 = NULL_TREE;
4737 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4739 expr = gfc_copy_expr (al->expr);
4741 if (expr->ts.type == BT_CLASS)
4742 gfc_add_data_component (expr);
4744 gfc_init_se (&se, NULL);
4746 se.want_pointer = 1;
4747 se.descriptor_only = 1;
4748 gfc_conv_expr (&se, expr);
4750 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen))
4752 /* A scalar or derived type. */
4754 /* Determine allocate size. */
4755 if (al->expr->ts.type == BT_CLASS && code->expr3)
4757 if (code->expr3->ts.type == BT_CLASS)
4759 sz = gfc_copy_expr (code->expr3);
4760 gfc_add_vptr_component (sz);
4761 gfc_add_size_component (sz);
4762 gfc_init_se (&se_sz, NULL);
4763 gfc_conv_expr (&se_sz, sz);
4764 gfc_free_expr (sz);
4765 memsz = se_sz.expr;
4767 else
4768 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
4770 else if (al->expr->ts.type == BT_CHARACTER
4771 && al->expr->ts.deferred && code->expr3)
4773 if (!code->expr3->ts.u.cl->backend_decl)
4775 /* Convert and use the length expression. */
4776 gfc_init_se (&se_sz, NULL);
4777 if (code->expr3->expr_type == EXPR_VARIABLE
4778 || code->expr3->expr_type == EXPR_CONSTANT)
4780 gfc_conv_expr (&se_sz, code->expr3);
4781 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4782 se_sz.string_length
4783 = gfc_evaluate_now (se_sz.string_length, &se.pre);
4784 gfc_add_block_to_block (&se.pre, &se_sz.post);
4785 memsz = se_sz.string_length;
4787 else if (code->expr3->mold
4788 && code->expr3->ts.u.cl
4789 && code->expr3->ts.u.cl->length)
4791 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
4792 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4793 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4794 gfc_add_block_to_block (&se.pre, &se_sz.post);
4795 memsz = se_sz.expr;
4797 else
4799 /* This is would be inefficient and possibly could
4800 generate wrong code if the result were not stored
4801 in expr3/slen3. */
4802 if (slen3 == NULL_TREE)
4804 gfc_conv_expr (&se_sz, code->expr3);
4805 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4806 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
4807 gfc_add_block_to_block (&post, &se_sz.post);
4808 slen3 = gfc_evaluate_now (se_sz.string_length,
4809 &se.pre);
4811 memsz = slen3;
4814 else
4815 /* Otherwise use the stored string length. */
4816 memsz = code->expr3->ts.u.cl->backend_decl;
4817 tmp = al->expr->ts.u.cl->backend_decl;
4819 /* Store the string length. */
4820 if (tmp && TREE_CODE (tmp) == VAR_DECL)
4821 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
4822 memsz));
4824 /* Convert to size in bytes, using the character KIND. */
4825 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
4826 tmp = TYPE_SIZE_UNIT (tmp);
4827 memsz = fold_build2_loc (input_location, MULT_EXPR,
4828 TREE_TYPE (tmp), tmp,
4829 fold_convert (TREE_TYPE (tmp), memsz));
4831 else if (al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4833 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
4834 gfc_init_se (&se_sz, NULL);
4835 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
4836 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4837 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4838 gfc_add_block_to_block (&se.pre, &se_sz.post);
4839 /* Store the string length. */
4840 tmp = al->expr->ts.u.cl->backend_decl;
4841 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
4842 se_sz.expr));
4843 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
4844 tmp = TYPE_SIZE_UNIT (tmp);
4845 memsz = fold_build2_loc (input_location, MULT_EXPR,
4846 TREE_TYPE (tmp), tmp,
4847 fold_convert (TREE_TYPE (se_sz.expr),
4848 se_sz.expr));
4850 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
4851 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
4852 else
4853 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
4855 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
4857 memsz = se.string_length;
4859 /* Convert to size in bytes, using the character KIND. */
4860 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
4861 tmp = TYPE_SIZE_UNIT (tmp);
4862 memsz = fold_build2_loc (input_location, MULT_EXPR,
4863 TREE_TYPE (tmp), tmp,
4864 fold_convert (TREE_TYPE (tmp), memsz));
4867 /* Allocate - for non-pointers with re-alloc checking. */
4868 if (gfc_expr_attr (expr).allocatable)
4869 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
4870 stat, errmsg, errlen, expr);
4871 else
4872 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
4874 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
4876 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
4877 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
4878 gfc_add_expr_to_block (&se.pre, tmp);
4882 gfc_add_block_to_block (&block, &se.pre);
4884 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
4885 if (code->expr1)
4887 /* The coarray library already sets the errmsg. */
4888 if (gfc_option.coarray == GFC_FCOARRAY_LIB
4889 && gfc_expr_attr (expr).codimension)
4890 tmp = build1_v (GOTO_EXPR, label_finish);
4891 else
4892 tmp = build1_v (GOTO_EXPR, label_errmsg);
4894 parm = fold_build2_loc (input_location, NE_EXPR,
4895 boolean_type_node, stat,
4896 build_int_cst (TREE_TYPE (stat), 0));
4897 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4898 gfc_unlikely(parm), tmp,
4899 build_empty_stmt (input_location));
4900 gfc_add_expr_to_block (&block, tmp);
4903 if (code->expr3 && !code->expr3->mold)
4905 /* Initialization via SOURCE block
4906 (or static default initializer). */
4907 gfc_expr *rhs = gfc_copy_expr (code->expr3);
4908 if (al->expr->ts.type == BT_CLASS)
4910 gfc_se call;
4911 gfc_actual_arglist *actual;
4912 gfc_expr *ppc;
4913 gfc_init_se (&call, NULL);
4914 /* Do a polymorphic deep copy. */
4915 actual = gfc_get_actual_arglist ();
4916 actual->expr = gfc_copy_expr (rhs);
4917 if (rhs->ts.type == BT_CLASS)
4918 gfc_add_data_component (actual->expr);
4919 actual->next = gfc_get_actual_arglist ();
4920 actual->next->expr = gfc_copy_expr (al->expr);
4921 gfc_add_data_component (actual->next->expr);
4922 if (rhs->ts.type == BT_CLASS)
4924 ppc = gfc_copy_expr (rhs);
4925 gfc_add_vptr_component (ppc);
4927 else
4928 ppc = gfc_lval_expr_from_sym (gfc_find_derived_vtab (rhs->ts.u.derived));
4929 gfc_add_component_ref (ppc, "_copy");
4930 gfc_conv_procedure_call (&call, ppc->symtree->n.sym, actual,
4931 ppc, NULL);
4932 gfc_add_expr_to_block (&call.pre, call.expr);
4933 gfc_add_block_to_block (&call.pre, &call.post);
4934 tmp = gfc_finish_block (&call.pre);
4936 else if (expr3 != NULL_TREE)
4938 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
4939 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
4940 slen3, expr3, code->expr3->ts.kind);
4941 tmp = NULL_TREE;
4943 else
4945 /* Switch off automatic reallocation since we have just done
4946 the ALLOCATE. */
4947 int realloc_lhs = gfc_option.flag_realloc_lhs;
4948 gfc_option.flag_realloc_lhs = 0;
4949 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
4950 rhs, false, false);
4951 gfc_option.flag_realloc_lhs = realloc_lhs;
4953 gfc_free_expr (rhs);
4954 gfc_add_expr_to_block (&block, tmp);
4956 else if (code->expr3 && code->expr3->mold
4957 && code->expr3->ts.type == BT_CLASS)
4959 /* Default-initialization via MOLD (polymorphic). */
4960 gfc_expr *rhs = gfc_copy_expr (code->expr3);
4961 gfc_se dst,src;
4962 gfc_add_vptr_component (rhs);
4963 gfc_add_def_init_component (rhs);
4964 gfc_init_se (&dst, NULL);
4965 gfc_init_se (&src, NULL);
4966 gfc_conv_expr (&dst, expr);
4967 gfc_conv_expr (&src, rhs);
4968 gfc_add_block_to_block (&block, &src.pre);
4969 tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz);
4970 gfc_add_expr_to_block (&block, tmp);
4971 gfc_free_expr (rhs);
4974 /* Allocation of CLASS entities. */
4975 gfc_free_expr (expr);
4976 expr = al->expr;
4977 if (expr->ts.type == BT_CLASS)
4979 gfc_expr *lhs,*rhs;
4980 gfc_se lse;
4982 /* Initialize VPTR for CLASS objects. */
4983 lhs = gfc_expr_to_initialize (expr);
4984 gfc_add_vptr_component (lhs);
4985 rhs = NULL;
4986 if (code->expr3 && code->expr3->ts.type == BT_CLASS)
4988 /* Polymorphic SOURCE: VPTR must be determined at run time. */
4989 rhs = gfc_copy_expr (code->expr3);
4990 gfc_add_vptr_component (rhs);
4991 tmp = gfc_trans_pointer_assignment (lhs, rhs);
4992 gfc_add_expr_to_block (&block, tmp);
4993 gfc_free_expr (rhs);
4995 else
4997 /* VPTR is fixed at compile time. */
4998 gfc_symbol *vtab;
4999 gfc_typespec *ts;
5000 if (code->expr3)
5001 ts = &code->expr3->ts;
5002 else if (expr->ts.type == BT_DERIVED)
5003 ts = &expr->ts;
5004 else if (code->ext.alloc.ts.type == BT_DERIVED)
5005 ts = &code->ext.alloc.ts;
5006 else if (expr->ts.type == BT_CLASS)
5007 ts = &CLASS_DATA (expr)->ts;
5008 else
5009 ts = &expr->ts;
5011 if (ts->type == BT_DERIVED)
5013 vtab = gfc_find_derived_vtab (ts->u.derived);
5014 gcc_assert (vtab);
5015 gfc_init_se (&lse, NULL);
5016 lse.want_pointer = 1;
5017 gfc_conv_expr (&lse, lhs);
5018 tmp = gfc_build_addr_expr (NULL_TREE,
5019 gfc_get_symbol_decl (vtab));
5020 gfc_add_modify (&block, lse.expr,
5021 fold_convert (TREE_TYPE (lse.expr), tmp));
5024 gfc_free_expr (lhs);
5029 /* STAT (ERRMSG only makes sense with STAT). */
5030 if (code->expr1)
5032 tmp = build1_v (LABEL_EXPR, label_errmsg);
5033 gfc_add_expr_to_block (&block, tmp);
5036 /* ERRMSG block. */
5037 if (code->expr2)
5039 /* A better error message may be possible, but not required. */
5040 const char *msg = "Attempt to allocate an allocated object";
5041 tree slen, dlen;
5043 gfc_init_se (&se, NULL);
5044 gfc_conv_expr_lhs (&se, code->expr2);
5046 errmsg = gfc_create_var (pchar_type_node, "ERRMSG");
5048 gfc_add_modify (&block, errmsg,
5049 gfc_build_addr_expr (pchar_type_node,
5050 gfc_build_localized_cstring_const (msg)));
5052 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5053 dlen = gfc_get_expr_charlen (code->expr2);
5054 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5055 slen);
5057 dlen = build_call_expr_loc (input_location,
5058 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5059 gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
5061 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5062 build_int_cst (TREE_TYPE (stat), 0));
5064 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5066 gfc_add_expr_to_block (&block, tmp);
5069 /* STAT (ERRMSG only makes sense with STAT). */
5070 if (code->expr1)
5072 tmp = build1_v (LABEL_EXPR, label_finish);
5073 gfc_add_expr_to_block (&block, tmp);
5076 /* STAT block. */
5077 if (code->expr1)
5079 gfc_init_se (&se, NULL);
5080 gfc_conv_expr_lhs (&se, code->expr1);
5081 tmp = convert (TREE_TYPE (se.expr), stat);
5082 gfc_add_modify (&block, se.expr, tmp);
5085 gfc_add_block_to_block (&block, &se.post);
5086 gfc_add_block_to_block (&block, &post);
5088 return gfc_finish_block (&block);
5092 /* Translate a DEALLOCATE statement. */
5094 tree
5095 gfc_trans_deallocate (gfc_code *code)
5097 gfc_se se;
5098 gfc_alloc *al;
5099 tree apstat, astat, pstat, stat, tmp;
5100 stmtblock_t block;
5102 pstat = apstat = stat = astat = tmp = NULL_TREE;
5104 gfc_start_block (&block);
5106 /* Count the number of failed deallocations. If deallocate() was
5107 called with STAT= , then set STAT to the count. If deallocate
5108 was called with ERRMSG, then set ERRMG to a string. */
5109 if (code->expr1 || code->expr2)
5111 tree gfc_int4_type_node = gfc_get_int_type (4);
5113 stat = gfc_create_var (gfc_int4_type_node, "stat");
5114 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5116 /* Running total of possible deallocation failures. */
5117 astat = gfc_create_var (gfc_int4_type_node, "astat");
5118 apstat = gfc_build_addr_expr (NULL_TREE, astat);
5120 /* Initialize astat to 0. */
5121 gfc_add_modify (&block, astat, build_int_cst (TREE_TYPE (astat), 0));
5124 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5126 gfc_expr *expr = gfc_copy_expr (al->expr);
5127 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5129 if (expr->ts.type == BT_CLASS)
5130 gfc_add_data_component (expr);
5132 gfc_init_se (&se, NULL);
5133 gfc_start_block (&se.pre);
5135 se.want_pointer = 1;
5136 se.descriptor_only = 1;
5137 gfc_conv_expr (&se, expr);
5139 if (expr->rank || gfc_expr_attr (expr).codimension)
5141 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
5143 gfc_ref *ref;
5144 gfc_ref *last = NULL;
5145 for (ref = expr->ref; ref; ref = ref->next)
5146 if (ref->type == REF_COMPONENT)
5147 last = ref;
5149 /* Do not deallocate the components of a derived type
5150 ultimate pointer component. */
5151 if (!(last && last->u.c.component->attr.pointer)
5152 && !(!last && expr->symtree->n.sym->attr.pointer))
5154 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5155 expr->rank);
5156 gfc_add_expr_to_block (&se.pre, tmp);
5159 tmp = gfc_array_deallocate (se.expr, pstat, expr);
5160 gfc_add_expr_to_block (&se.pre, tmp);
5162 else
5164 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5165 expr, expr->ts);
5166 gfc_add_expr_to_block (&se.pre, tmp);
5168 /* Set to zero after deallocation. */
5169 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5170 se.expr,
5171 build_int_cst (TREE_TYPE (se.expr), 0));
5172 gfc_add_expr_to_block (&se.pre, tmp);
5174 if (al->expr->ts.type == BT_CLASS)
5176 /* Reset _vptr component to declared type. */
5177 gfc_expr *rhs, *lhs = gfc_copy_expr (al->expr);
5178 gfc_symbol *vtab = gfc_find_derived_vtab (al->expr->ts.u.derived);
5179 gfc_add_vptr_component (lhs);
5180 rhs = gfc_lval_expr_from_sym (vtab);
5181 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5182 gfc_add_expr_to_block (&se.pre, tmp);
5183 gfc_free_expr (lhs);
5184 gfc_free_expr (rhs);
5188 /* Keep track of the number of failed deallocations by adding stat
5189 of the last deallocation to the running total. */
5190 if (code->expr1 || code->expr2)
5192 apstat = fold_build2_loc (input_location, PLUS_EXPR,
5193 TREE_TYPE (stat), astat, stat);
5194 gfc_add_modify (&se.pre, astat, apstat);
5197 tmp = gfc_finish_block (&se.pre);
5198 gfc_add_expr_to_block (&block, tmp);
5199 gfc_free_expr (expr);
5202 /* Set STAT. */
5203 if (code->expr1)
5205 gfc_init_se (&se, NULL);
5206 gfc_conv_expr_lhs (&se, code->expr1);
5207 tmp = convert (TREE_TYPE (se.expr), astat);
5208 gfc_add_modify (&block, se.expr, tmp);
5211 /* Set ERRMSG. */
5212 if (code->expr2)
5214 /* A better error message may be possible, but not required. */
5215 const char *msg = "Attempt to deallocate an unallocated object";
5216 tree errmsg, slen, dlen;
5218 gfc_init_se (&se, NULL);
5219 gfc_conv_expr_lhs (&se, code->expr2);
5221 errmsg = gfc_create_var (pchar_type_node, "ERRMSG");
5223 gfc_add_modify (&block, errmsg,
5224 gfc_build_addr_expr (pchar_type_node,
5225 gfc_build_localized_cstring_const (msg)));
5227 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5228 dlen = gfc_get_expr_charlen (code->expr2);
5229 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5230 slen);
5232 dlen = build_call_expr_loc (input_location,
5233 builtin_decl_explicit (BUILT_IN_MEMCPY), 3,
5234 gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
5236 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, astat,
5237 build_int_cst (TREE_TYPE (astat), 0));
5239 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5241 gfc_add_expr_to_block (&block, tmp);
5244 return gfc_finish_block (&block);
5247 #include "gt-fortran-trans-stmt.h"