]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-stmt.c
t-uclinux (M68K_MLIB_CPU): Check for FL_UCLINUX.
[thirdparty/gcc.git] / gcc / fortran / trans-stmt.c
CommitLineData
6de9cd9a 1/* Statement translation -- generate GCC trees from gfc_code.
8b791297 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
bfcabc6c 3 Free Software Foundation, Inc.
6de9cd9a
DN
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6
9fc4d79b 7This file is part of GCC.
6de9cd9a 8
9fc4d79b
TS
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
d234d788 11Software Foundation; either version 3, or (at your option) any later
9fc4d79b 12version.
6de9cd9a 13
9fc4d79b
TS
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
6de9cd9a
DN
18
19You should have received a copy of the GNU General Public License
d234d788
NC
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
6de9cd9a
DN
22
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "tree.h"
726a989a 28#include "gimple.h"
6de9cd9a
DN
29#include "ggc.h"
30#include "toplev.h"
31#include "real.h"
6de9cd9a 32#include "gfortran.h"
dd18a33b 33#include "flags.h"
6de9cd9a
DN
34#include "trans.h"
35#include "trans-stmt.h"
36#include "trans-types.h"
37#include "trans-array.h"
38#include "trans-const.h"
39#include "arith.h"
3ded6210 40#include "dependency.h"
6de9cd9a 41
6de9cd9a
DN
42typedef struct iter_info
43{
44 tree var;
45 tree start;
46 tree end;
47 tree step;
48 struct iter_info *next;
49}
50iter_info;
51
6de9cd9a
DN
52typedef struct forall_info
53{
54 iter_info *this_loop;
55 tree mask;
6de9cd9a
DN
56 tree maskindex;
57 int nvar;
58 tree size;
e8d366ec 59 struct forall_info *prev_nest;
6de9cd9a
DN
60}
61forall_info;
62
011daa76
RS
63static void gfc_trans_where_2 (gfc_code *, tree, bool,
64 forall_info *, stmtblock_t *);
6de9cd9a
DN
65
66/* Translate a F95 label number to a LABEL_EXPR. */
67
68tree
69gfc_trans_label_here (gfc_code * code)
70{
71 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
72}
73
ce2df7c6
FW
74
75/* Given a variable expression which has been ASSIGNed to, find the decl
76 containing the auxiliary variables. For variables in common blocks this
77 is a field_decl. */
78
79void
80gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
81{
82 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
83 gfc_conv_expr (se, expr);
84 /* Deals with variable in common block. Get the field declaration. */
85 if (TREE_CODE (se->expr) == COMPONENT_REF)
86 se->expr = TREE_OPERAND (se->expr, 1);
910450c1
FW
87 /* Deals with dummy argument. Get the parameter declaration. */
88 else if (TREE_CODE (se->expr) == INDIRECT_REF)
89 se->expr = TREE_OPERAND (se->expr, 0);
ce2df7c6
FW
90}
91
6de9cd9a 92/* Translate a label assignment statement. */
ce2df7c6 93
6de9cd9a
DN
94tree
95gfc_trans_label_assign (gfc_code * code)
96{
97 tree label_tree;
98 gfc_se se;
99 tree len;
100 tree addr;
101 tree len_tree;
6de9cd9a
DN
102 int label_len;
103
104 /* Start a new block. */
105 gfc_init_se (&se, NULL);
106 gfc_start_block (&se.pre);
ce2df7c6
FW
107 gfc_conv_label_variable (&se, code->expr);
108
6de9cd9a
DN
109 len = GFC_DECL_STRING_LEN (se.expr);
110 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
111
112 label_tree = gfc_get_label_decl (code->label);
113
114 if (code->label->defined == ST_LABEL_TARGET)
115 {
116 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
117 len_tree = integer_minus_one_node;
118 }
119 else
120 {
d393bbd7
FXC
121 gfc_expr *format = code->label->format;
122
123 label_len = format->value.character.length;
7d60be94 124 len_tree = build_int_cst (NULL_TREE, label_len);
d393bbd7
FXC
125 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
126 format->value.character.string);
b078dfbf 127 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
6de9cd9a
DN
128 }
129
726a989a
RB
130 gfc_add_modify (&se.pre, len, len_tree);
131 gfc_add_modify (&se.pre, addr, label_tree);
6de9cd9a
DN
132
133 return gfc_finish_block (&se.pre);
134}
135
136/* Translate a GOTO statement. */
137
138tree
139gfc_trans_goto (gfc_code * code)
140{
dd18a33b 141 locus loc = code->loc;
6de9cd9a
DN
142 tree assigned_goto;
143 tree target;
144 tree tmp;
6de9cd9a
DN
145 gfc_se se;
146
6de9cd9a
DN
147 if (code->label != NULL)
148 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
149
150 /* ASSIGNED GOTO. */
151 gfc_init_se (&se, NULL);
152 gfc_start_block (&se.pre);
ce2df7c6 153 gfc_conv_label_variable (&se, code->expr);
6de9cd9a 154 tmp = GFC_DECL_STRING_LEN (se.expr);
3f2ec06a
RG
155 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp,
156 build_int_cst (TREE_TYPE (tmp), -1));
0d52899f 157 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
c8fe94c7 158 "Assigned label is not a target label");
6de9cd9a
DN
159
160 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
6de9cd9a
DN
161
162 code = code->block;
163 if (code == NULL)
164 {
44855d8c 165 target = fold_build1 (GOTO_EXPR, void_type_node, assigned_goto);
6de9cd9a
DN
166 gfc_add_expr_to_block (&se.pre, target);
167 return gfc_finish_block (&se.pre);
168 }
169
170 /* Check the label list. */
6de9cd9a
DN
171 do
172 {
75d2cf69
SB
173 target = gfc_get_label_decl (code->label);
174 tmp = gfc_build_addr_expr (pvoid_type_node, target);
44855d8c 175 tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, assigned_goto);
75d2cf69 176 tmp = build3_v (COND_EXPR, tmp,
44855d8c 177 fold_build1 (GOTO_EXPR, void_type_node, target),
75d2cf69 178 build_empty_stmt ());
6de9cd9a
DN
179 gfc_add_expr_to_block (&se.pre, tmp);
180 code = code->block;
181 }
182 while (code != NULL);
0d52899f 183 gfc_trans_runtime_check (true, false, boolean_true_node, &se.pre, &loc,
c8fe94c7 184 "Assigned label is not in the list");
dd18a33b 185
6de9cd9a
DN
186 return gfc_finish_block (&se.pre);
187}
188
189
3d79abbd
PB
190/* Translate an ENTRY statement. Just adds a label for this entry point. */
191tree
192gfc_trans_entry (gfc_code * code)
193{
194 return build1_v (LABEL_EXPR, code->ext.entry->label);
195}
196
197
476220e7
PT
198/* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
199 elemental subroutines. Make temporaries for output arguments if any such
200 dependencies are found. Output arguments are chosen because internal_unpack
201 can be used, as is, to copy the result back to the variable. */
202static void
203gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
2b0bd714
MM
204 gfc_symbol * sym, gfc_actual_arglist * arg,
205 gfc_dep_check check_variable)
476220e7
PT
206{
207 gfc_actual_arglist *arg0;
208 gfc_expr *e;
209 gfc_formal_arglist *formal;
210 gfc_loopinfo tmp_loop;
211 gfc_se parmse;
212 gfc_ss *ss;
213 gfc_ss_info *info;
214 gfc_symbol *fsym;
215 int n;
476220e7
PT
216 tree data;
217 tree offset;
218 tree size;
219 tree tmp;
220
221 if (loopse->ss == NULL)
222 return;
223
224 ss = loopse->ss;
225 arg0 = arg;
226 formal = sym->formal;
227
228 /* Loop over all the arguments testing for dependencies. */
229 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
230 {
231 e = arg->expr;
232 if (e == NULL)
233 continue;
234
235 /* Obtain the info structure for the current argument. */
236 info = NULL;
237 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
238 {
239 if (ss->expr != e)
240 continue;
241 info = &ss->data.info;
242 break;
243 }
244
245 /* If there is a dependency, create a temporary and use it
66e4ab31 246 instead of the variable. */
476220e7
PT
247 fsym = formal ? formal->sym : NULL;
248 if (e->expr_type == EXPR_VARIABLE
249 && e->rank && fsym
06bcd751
PT
250 && fsym->attr.intent != INTENT_IN
251 && gfc_check_fncall_dependency (e, fsym->attr.intent,
2b0bd714 252 sym, arg0, check_variable))
476220e7 253 {
79e5286c 254 tree initial, temptype;
12f681a0
DK
255 stmtblock_t temp_post;
256
476220e7
PT
257 /* Make a local loopinfo for the temporary creation, so that
258 none of the other ss->info's have to be renormalized. */
259 gfc_init_loopinfo (&tmp_loop);
260 for (n = 0; n < info->dimen; n++)
261 {
262 tmp_loop.to[n] = loopse->loop->to[n];
263 tmp_loop.from[n] = loopse->loop->from[n];
264 tmp_loop.order[n] = loopse->loop->order[n];
265 }
266
12f681a0
DK
267 /* Obtain the argument descriptor for unpacking. */
268 gfc_init_se (&parmse, NULL);
269 parmse.want_pointer = 1;
270 gfc_conv_expr_descriptor (&parmse, e, gfc_walk_expr (e));
271 gfc_add_block_to_block (&se->pre, &parmse.pre);
272
eb74e79b
PT
273 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
274 initialize the array temporary with a copy of the values. */
275 if (fsym->attr.intent == INTENT_INOUT
276 || (fsym->ts.type ==BT_DERIVED
277 && fsym->attr.intent == INTENT_OUT))
12f681a0
DK
278 initial = parmse.expr;
279 else
280 initial = NULL_TREE;
281
79e5286c
DK
282 /* Find the type of the temporary to create; we don't use the type
283 of e itself as this breaks for subcomponent-references in e (where
284 the type of e is that of the final reference, but parmse.expr's
285 type corresponds to the full derived-type). */
286 /* TODO: Fix this somehow so we don't need a temporary of the whole
287 array but instead only the components referenced. */
288 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
289 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
290 temptype = TREE_TYPE (temptype);
291 temptype = gfc_get_element_type (temptype);
292
293 /* Generate the temporary. Cleaning up the temporary should be the
294 very last thing done, so we add the code to a new block and add it
295 to se->post as last instructions. */
476220e7
PT
296 size = gfc_create_var (gfc_array_index_type, NULL);
297 data = gfc_create_var (pvoid_type_node, NULL);
12f681a0 298 gfc_init_block (&temp_post);
12f681a0 299 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post,
79e5286c 300 &tmp_loop, info, temptype,
12f681a0
DK
301 initial,
302 false, true, false,
303 &arg->expr->where);
726a989a 304 gfc_add_modify (&se->pre, size, tmp);
476220e7 305 tmp = fold_convert (pvoid_type_node, info->data);
726a989a 306 gfc_add_modify (&se->pre, data, tmp);
476220e7 307
476220e7
PT
308 /* Calculate the offset for the temporary. */
309 offset = gfc_index_zero_node;
310 for (n = 0; n < info->dimen; n++)
311 {
312 tmp = gfc_conv_descriptor_stride (info->descriptor,
313 gfc_rank_cst[n]);
314 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
315 loopse->loop->from[n], tmp);
316 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type,
317 offset, tmp);
318 }
319 info->offset = gfc_create_var (gfc_array_index_type, NULL);
726a989a 320 gfc_add_modify (&se->pre, info->offset, offset);
476220e7
PT
321
322 /* Copy the result back using unpack. */
5039610b 323 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, parmse.expr, data);
476220e7
PT
324 gfc_add_expr_to_block (&se->post, tmp);
325
79e5286c 326 /* parmse.pre is already added above. */
476220e7 327 gfc_add_block_to_block (&se->post, &parmse.post);
12f681a0 328 gfc_add_block_to_block (&se->post, &temp_post);
476220e7
PT
329 }
330 }
331}
332
333
6de9cd9a
DN
334/* Translate the CALL statement. Builds a call to an F95 subroutine. */
335
336tree
eb74e79b
PT
337gfc_trans_call (gfc_code * code, bool dependency_check,
338 tree mask, tree count1, bool invert)
6de9cd9a
DN
339{
340 gfc_se se;
48474141 341 gfc_ss * ss;
dda895f9 342 int has_alternate_specifier;
2b0bd714 343 gfc_dep_check check_variable;
eb74e79b
PT
344 tree index = NULL_TREE;
345 tree maskexpr = NULL_TREE;
346 tree tmp;
6de9cd9a
DN
347
348 /* A CALL starts a new block because the actual arguments may have to
349 be evaluated first. */
350 gfc_init_se (&se, NULL);
351 gfc_start_block (&se.pre);
352
6e45f57b 353 gcc_assert (code->resolved_sym);
6de9cd9a 354
48474141
PT
355 ss = gfc_ss_terminator;
356 if (code->resolved_sym->attr.elemental)
357 ss = gfc_walk_elemental_function_args (ss, code->ext.actual, GFC_SS_REFERENCE);
6de9cd9a 358
48474141
PT
359 /* Is not an elemental subroutine call with array valued arguments. */
360 if (ss == gfc_ss_terminator)
6de9cd9a 361 {
48474141
PT
362
363 /* Translate the call. */
364 has_alternate_specifier
713485cc
JW
365 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
366 code->expr, NULL_TREE);
48474141
PT
367
368 /* A subroutine without side-effect, by definition, does nothing! */
369 TREE_SIDE_EFFECTS (se.expr) = 1;
370
371 /* Chain the pieces together and return the block. */
372 if (has_alternate_specifier)
373 {
374 gfc_code *select_code;
375 gfc_symbol *sym;
376 select_code = code->next;
377 gcc_assert(select_code->op == EXEC_SELECT);
378 sym = select_code->expr->symtree->n.sym;
379 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
9ebe2d22
PT
380 if (sym->backend_decl == NULL)
381 sym->backend_decl = gfc_get_symbol_decl (sym);
726a989a 382 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
48474141
PT
383 }
384 else
385 gfc_add_expr_to_block (&se.pre, se.expr);
386
387 gfc_add_block_to_block (&se.pre, &se.post);
6de9cd9a 388 }
48474141 389
6de9cd9a 390 else
48474141
PT
391 {
392 /* An elemental subroutine call with array valued arguments has
393 to be scalarized. */
394 gfc_loopinfo loop;
395 stmtblock_t body;
396 stmtblock_t block;
397 gfc_se loopse;
70e72065 398 gfc_se depse;
48474141
PT
399
400 /* gfc_walk_elemental_function_args renders the ss chain in the
12f681a0 401 reverse order to the actual argument order. */
48474141
PT
402 ss = gfc_reverse_ss (ss);
403
404 /* Initialize the loop. */
405 gfc_init_se (&loopse, NULL);
406 gfc_init_loopinfo (&loop);
407 gfc_add_ss_to_loop (&loop, ss);
408
409 gfc_conv_ss_startstride (&loop);
2b0bd714
MM
410 /* TODO: gfc_conv_loop_setup generates a temporary for vector
411 subscripts. This could be prevented in the elemental case
412 as temporaries are handled separatedly
413 (below in gfc_conv_elemental_dependencies). */
bdfd2ff0 414 gfc_conv_loop_setup (&loop, &code->expr->where);
48474141
PT
415 gfc_mark_ss_chain_used (ss, 1);
416
476220e7
PT
417 /* Convert the arguments, checking for dependencies. */
418 gfc_copy_loopinfo_to_se (&loopse, &loop);
419 loopse.ss = ss;
420
06bcd751 421 /* For operator assignment, do dependency checking. */
476220e7 422 if (dependency_check)
2b0bd714
MM
423 check_variable = ELEM_CHECK_VARIABLE;
424 else
425 check_variable = ELEM_DONT_CHECK_VARIABLE;
70e72065
MM
426
427 gfc_init_se (&depse, NULL);
428 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
2b0bd714 429 code->ext.actual, check_variable);
476220e7 430
70e72065
MM
431 gfc_add_block_to_block (&loop.pre, &depse.pre);
432 gfc_add_block_to_block (&loop.post, &depse.post);
433
48474141
PT
434 /* Generate the loop body. */
435 gfc_start_scalarized_body (&loop, &body);
436 gfc_init_block (&block);
48474141 437
eb74e79b
PT
438 if (mask && count1)
439 {
440 /* Form the mask expression according to the mask. */
441 index = count1;
442 maskexpr = gfc_build_array_ref (mask, index, NULL);
443 if (invert)
444 maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr),
445 maskexpr);
446 }
447
48474141 448 /* Add the subroutine call to the block. */
eb74e79b
PT
449 gfc_conv_procedure_call (&loopse, code->resolved_sym,
450 code->ext.actual, code->expr,
451 NULL_TREE);
452
453 if (mask && count1)
454 {
455 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
456 build_empty_stmt ());
457 gfc_add_expr_to_block (&loopse.pre, tmp);
458 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
459 count1, gfc_index_one_node);
460 gfc_add_modify (&loopse.pre, count1, tmp);
461 }
462 else
463 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
48474141
PT
464
465 gfc_add_block_to_block (&block, &loopse.pre);
466 gfc_add_block_to_block (&block, &loopse.post);
467
468 /* Finish up the loop block and the loop. */
469 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
470 gfc_trans_scalarizing_loops (&loop, &body);
471 gfc_add_block_to_block (&se.pre, &loop.pre);
472 gfc_add_block_to_block (&se.pre, &loop.post);
476220e7 473 gfc_add_block_to_block (&se.pre, &se.post);
48474141
PT
474 gfc_cleanup_loop (&loop);
475 }
6de9cd9a 476
6de9cd9a
DN
477 return gfc_finish_block (&se.pre);
478}
479
480
481/* Translate the RETURN statement. */
482
483tree
484gfc_trans_return (gfc_code * code ATTRIBUTE_UNUSED)
485{
486 if (code->expr)
487 {
488 gfc_se se;
489 tree tmp;
490 tree result;
491
da4c6ed8 492 /* If code->expr is not NULL, this return statement must appear
6de9cd9a
DN
493 in a subroutine and current_fake_result_decl has already
494 been generated. */
495
5f20c93a 496 result = gfc_get_fake_result_decl (NULL, 0);
6de9cd9a
DN
497 if (!result)
498 {
499 gfc_warning ("An alternate return at %L without a * dummy argument",
500 &code->expr->where);
501 return build1_v (GOTO_EXPR, gfc_get_return_label ());
502 }
503
504 /* Start a new block for this statement. */
505 gfc_init_se (&se, NULL);
506 gfc_start_block (&se.pre);
507
508 gfc_conv_expr (&se, code->expr);
509
44855d8c
TS
510 tmp = fold_build2 (MODIFY_EXPR, TREE_TYPE (result), result,
511 fold_convert (TREE_TYPE (result), se.expr));
6de9cd9a
DN
512 gfc_add_expr_to_block (&se.pre, tmp);
513
514 tmp = build1_v (GOTO_EXPR, gfc_get_return_label ());
515 gfc_add_expr_to_block (&se.pre, tmp);
516 gfc_add_block_to_block (&se.pre, &se.post);
517 return gfc_finish_block (&se.pre);
518 }
519 else
520 return build1_v (GOTO_EXPR, gfc_get_return_label ());
521}
522
523
524/* Translate the PAUSE statement. We have to translate this statement
525 to a runtime library call. */
526
527tree
528gfc_trans_pause (gfc_code * code)
529{
e2cad04b 530 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 531 gfc_se se;
6de9cd9a 532 tree tmp;
6de9cd9a
DN
533
534 /* Start a new block for this statement. */
535 gfc_init_se (&se, NULL);
536 gfc_start_block (&se.pre);
537
538
539 if (code->expr == NULL)
540 {
7d60be94 541 tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
5039610b 542 tmp = build_call_expr (gfor_fndecl_pause_numeric, 1, tmp);
6de9cd9a
DN
543 }
544 else
545 {
546 gfc_conv_expr_reference (&se, code->expr);
5039610b
SL
547 tmp = build_call_expr (gfor_fndecl_pause_string, 2,
548 se.expr, se.string_length);
6de9cd9a
DN
549 }
550
6de9cd9a
DN
551 gfc_add_expr_to_block (&se.pre, tmp);
552
553 gfc_add_block_to_block (&se.pre, &se.post);
554
555 return gfc_finish_block (&se.pre);
556}
557
558
559/* Translate the STOP statement. We have to translate this statement
560 to a runtime library call. */
561
562tree
563gfc_trans_stop (gfc_code * code)
564{
e2cad04b 565 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 566 gfc_se se;
6de9cd9a 567 tree tmp;
6de9cd9a
DN
568
569 /* Start a new block for this statement. */
570 gfc_init_se (&se, NULL);
571 gfc_start_block (&se.pre);
572
573
574 if (code->expr == NULL)
575 {
7d60be94 576 tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
5039610b 577 tmp = build_call_expr (gfor_fndecl_stop_numeric, 1, tmp);
6de9cd9a
DN
578 }
579 else
580 {
581 gfc_conv_expr_reference (&se, code->expr);
5039610b
SL
582 tmp = build_call_expr (gfor_fndecl_stop_string, 2,
583 se.expr, se.string_length);
6de9cd9a
DN
584 }
585
6de9cd9a
DN
586 gfc_add_expr_to_block (&se.pre, tmp);
587
588 gfc_add_block_to_block (&se.pre, &se.post);
589
590 return gfc_finish_block (&se.pre);
591}
592
593
594/* Generate GENERIC for the IF construct. This function also deals with
595 the simple IF statement, because the front end translates the IF
596 statement into an IF construct.
597
598 We translate:
599
600 IF (cond) THEN
601 then_clause
602 ELSEIF (cond2)
603 elseif_clause
604 ELSE
605 else_clause
606 ENDIF
607
608 into:
609
610 pre_cond_s;
611 if (cond_s)
612 {
613 then_clause;
614 }
615 else
616 {
617 pre_cond_s
618 if (cond_s)
619 {
620 elseif_clause
621 }
622 else
623 {
624 else_clause;
625 }
626 }
627
628 where COND_S is the simplified version of the predicate. PRE_COND_S
629 are the pre side-effects produced by the translation of the
630 conditional.
631 We need to build the chain recursively otherwise we run into
632 problems with folding incomplete statements. */
633
634static tree
635gfc_trans_if_1 (gfc_code * code)
636{
637 gfc_se if_se;
638 tree stmt, elsestmt;
639
640 /* Check for an unconditional ELSE clause. */
641 if (!code->expr)
642 return gfc_trans_code (code->next);
643
644 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
645 gfc_init_se (&if_se, NULL);
646 gfc_start_block (&if_se.pre);
647
648 /* Calculate the IF condition expression. */
649 gfc_conv_expr_val (&if_se, code->expr);
650
651 /* Translate the THEN clause. */
652 stmt = gfc_trans_code (code->next);
653
654 /* Translate the ELSE clause. */
655 if (code->block)
656 elsestmt = gfc_trans_if_1 (code->block);
657 else
658 elsestmt = build_empty_stmt ();
659
660 /* Build the condition expression and add it to the condition block. */
61ead135 661 stmt = fold_build3 (COND_EXPR, void_type_node, if_se.expr, stmt, elsestmt);
6de9cd9a
DN
662
663 gfc_add_expr_to_block (&if_se.pre, stmt);
664
665 /* Finish off this statement. */
666 return gfc_finish_block (&if_se.pre);
667}
668
669tree
670gfc_trans_if (gfc_code * code)
671{
672 /* Ignore the top EXEC_IF, it only announces an IF construct. The
673 actual code we must translate is in code->block. */
674
675 return gfc_trans_if_1 (code->block);
676}
677
678
fa951694 679/* Translate an arithmetic IF expression.
6de9cd9a
DN
680
681 IF (cond) label1, label2, label3 translates to
682
683 if (cond <= 0)
684 {
685 if (cond < 0)
686 goto label1;
687 else // cond == 0
688 goto label2;
689 }
690 else // cond > 0
691 goto label3;
442c1644
CY
692
693 An optimized version can be generated in case of equal labels.
694 E.g., if label1 is equal to label2, we can translate it to
695
696 if (cond <= 0)
697 goto label1;
698 else
699 goto label3;
6de9cd9a
DN
700*/
701
702tree
703gfc_trans_arithmetic_if (gfc_code * code)
704{
705 gfc_se se;
706 tree tmp;
707 tree branch1;
708 tree branch2;
709 tree zero;
710
711 /* Start a new block. */
712 gfc_init_se (&se, NULL);
713 gfc_start_block (&se.pre);
714
715 /* Pre-evaluate COND. */
716 gfc_conv_expr_val (&se, code->expr);
5ec1334b 717 se.expr = gfc_evaluate_now (se.expr, &se.pre);
6de9cd9a
DN
718
719 /* Build something to compare with. */
720 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
721
442c1644
CY
722 if (code->label->value != code->label2->value)
723 {
724 /* If (cond < 0) take branch1 else take branch2.
725 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
726 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
727 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
728
729 if (code->label->value != code->label3->value)
61ead135 730 tmp = fold_build2 (LT_EXPR, boolean_type_node, se.expr, zero);
442c1644 731 else
61ead135 732 tmp = fold_build2 (NE_EXPR, boolean_type_node, se.expr, zero);
6de9cd9a 733
61ead135 734 branch1 = fold_build3 (COND_EXPR, void_type_node, tmp, branch1, branch2);
442c1644
CY
735 }
736 else
737 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
6de9cd9a 738
442c1644
CY
739 if (code->label->value != code->label3->value
740 && code->label2->value != code->label3->value)
741 {
742 /* if (cond <= 0) take branch1 else take branch2. */
743 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
61ead135
RG
744 tmp = fold_build2 (LE_EXPR, boolean_type_node, se.expr, zero);
745 branch1 = fold_build3 (COND_EXPR, void_type_node, tmp, branch1, branch2);
442c1644 746 }
6de9cd9a
DN
747
748 /* Append the COND_EXPR to the evaluation of COND, and return. */
749 gfc_add_expr_to_block (&se.pre, branch1);
750 return gfc_finish_block (&se.pre);
751}
752
753
54c2d931 754/* Translate the simple DO construct. This is where the loop variable has
fbdad37d
PB
755 integer type and step +-1. We can't use this in the general case
756 because integer overflow and floating point errors could give incorrect
757 results.
758 We translate a do loop from:
759
760 DO dovar = from, to, step
761 body
762 END DO
763
764 to:
765
766 [Evaluate loop bounds and step]
767 dovar = from;
768 if ((step > 0) ? (dovar <= to) : (dovar => to))
769 {
770 for (;;)
771 {
772 body;
773 cycle_label:
774 cond = (dovar == to);
775 dovar += step;
776 if (cond) goto end_label;
777 }
778 }
779 end_label:
780
781 This helps the optimizers by avoiding the extra induction variable
782 used in the general case. */
783
784static tree
785gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
786 tree from, tree to, tree step)
787{
788 stmtblock_t body;
789 tree type;
790 tree cond;
791 tree tmp;
33abc845 792 tree saved_dovar = NULL;
fbdad37d
PB
793 tree cycle_label;
794 tree exit_label;
795
796 type = TREE_TYPE (dovar);
797
798 /* Initialize the DO variable: dovar = from. */
726a989a 799 gfc_add_modify (pblock, dovar, from);
33abc845
TB
800
801 /* Save value for do-tinkering checking. */
802 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
803 {
804 saved_dovar = gfc_create_var (type, ".saved_dovar");
805 gfc_add_modify (pblock, saved_dovar, dovar);
806 }
fbdad37d
PB
807
808 /* Cycle and exit statements are implemented with gotos. */
809 cycle_label = gfc_build_label_decl (NULL_TREE);
810 exit_label = gfc_build_label_decl (NULL_TREE);
811
812 /* Put the labels where they can be found later. See gfc_trans_do(). */
813 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
814
815 /* Loop body. */
816 gfc_start_block (&body);
817
818 /* Main loop body. */
819 tmp = gfc_trans_code (code->block->next);
820 gfc_add_expr_to_block (&body, tmp);
821
822 /* Label for cycle statements (if needed). */
823 if (TREE_USED (cycle_label))
824 {
825 tmp = build1_v (LABEL_EXPR, cycle_label);
826 gfc_add_expr_to_block (&body, tmp);
827 }
828
33abc845
TB
829 /* Check whether someone has modified the loop variable. */
830 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
831 {
832 tmp = fold_build2 (NE_EXPR, boolean_type_node, dovar, saved_dovar);
833 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
834 "Loop variable has been modified");
835 }
836
fbdad37d 837 /* Evaluate the loop condition. */
61ead135 838 cond = fold_build2 (EQ_EXPR, boolean_type_node, dovar, to);
fbdad37d
PB
839 cond = gfc_evaluate_now (cond, &body);
840
841 /* Increment the loop variable. */
61ead135 842 tmp = fold_build2 (PLUS_EXPR, type, dovar, step);
726a989a 843 gfc_add_modify (&body, dovar, tmp);
fbdad37d 844
33abc845
TB
845 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
846 gfc_add_modify (&body, saved_dovar, dovar);
847
fbdad37d
PB
848 /* The loop exit. */
849 tmp = build1_v (GOTO_EXPR, exit_label);
850 TREE_USED (exit_label) = 1;
61ead135
RG
851 tmp = fold_build3 (COND_EXPR, void_type_node,
852 cond, tmp, build_empty_stmt ());
fbdad37d
PB
853 gfc_add_expr_to_block (&body, tmp);
854
855 /* Finish the loop body. */
856 tmp = gfc_finish_block (&body);
857 tmp = build1_v (LOOP_EXPR, tmp);
858
859 /* Only execute the loop if the number of iterations is positive. */
860 if (tree_int_cst_sgn (step) > 0)
10c7a96f 861 cond = fold_build2 (LE_EXPR, boolean_type_node, dovar, to);
fbdad37d 862 else
10c7a96f 863 cond = fold_build2 (GE_EXPR, boolean_type_node, dovar, to);
61ead135
RG
864 tmp = fold_build3 (COND_EXPR, void_type_node,
865 cond, tmp, build_empty_stmt ());
fbdad37d
PB
866 gfc_add_expr_to_block (pblock, tmp);
867
868 /* Add the exit label. */
869 tmp = build1_v (LABEL_EXPR, exit_label);
870 gfc_add_expr_to_block (pblock, tmp);
871
872 return gfc_finish_block (pblock);
873}
874
6de9cd9a
DN
875/* Translate the DO construct. This obviously is one of the most
876 important ones to get right with any compiler, but especially
877 so for Fortran.
878
fbdad37d
PB
879 We special case some loop forms as described in gfc_trans_simple_do.
880 For other cases we implement them with a separate loop count,
881 as described in the standard.
6de9cd9a
DN
882
883 We translate a do loop from:
884
885 DO dovar = from, to, step
886 body
887 END DO
888
889 to:
890
fbdad37d 891 [evaluate loop bounds and step]
5d148c08
FXC
892 empty = (step > 0 ? to < from : to > from);
893 countm1 = (to - from) / step;
fbdad37d 894 dovar = from;
5d148c08 895 if (empty) goto exit_label;
fbdad37d 896 for (;;)
6de9cd9a
DN
897 {
898 body;
899cycle_label:
fbdad37d 900 dovar += step
5d148c08 901 if (countm1 ==0) goto exit_label;
76dac339 902 countm1--;
6de9cd9a
DN
903 }
904exit_label:
905
5d148c08
FXC
906 countm1 is an unsigned integer. It is equal to the loop count minus one,
907 because the loop count itself can overflow. */
6de9cd9a
DN
908
909tree
910gfc_trans_do (gfc_code * code)
911{
912 gfc_se se;
913 tree dovar;
33abc845 914 tree saved_dovar = NULL;
6de9cd9a
DN
915 tree from;
916 tree to;
917 tree step;
5d148c08 918 tree countm1;
6de9cd9a 919 tree type;
5d148c08 920 tree utype;
6de9cd9a
DN
921 tree cond;
922 tree cycle_label;
923 tree exit_label;
924 tree tmp;
5d148c08 925 tree pos_step;
6de9cd9a
DN
926 stmtblock_t block;
927 stmtblock_t body;
928
929 gfc_start_block (&block);
930
fbdad37d 931 /* Evaluate all the expressions in the iterator. */
6de9cd9a
DN
932 gfc_init_se (&se, NULL);
933 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
934 gfc_add_block_to_block (&block, &se.pre);
935 dovar = se.expr;
936 type = TREE_TYPE (dovar);
937
938 gfc_init_se (&se, NULL);
8d5cfa27 939 gfc_conv_expr_val (&se, code->ext.iterator->start);
6de9cd9a 940 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 941 from = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
942
943 gfc_init_se (&se, NULL);
8d5cfa27 944 gfc_conv_expr_val (&se, code->ext.iterator->end);
6de9cd9a 945 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 946 to = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
947
948 gfc_init_se (&se, NULL);
8d5cfa27 949 gfc_conv_expr_val (&se, code->ext.iterator->step);
6de9cd9a 950 gfc_add_block_to_block (&block, &se.pre);
fbdad37d
PB
951 step = gfc_evaluate_now (se.expr, &block);
952
33abc845
TB
953 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
954 {
955 tmp = fold_build2 (EQ_EXPR, boolean_type_node, step,
956 fold_convert (type, integer_zero_node));
957 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
958 "DO step value is zero");
959 }
960
fbdad37d
PB
961 /* Special case simple loops. */
962 if (TREE_CODE (type) == INTEGER_TYPE
963 && (integer_onep (step)
964 || tree_int_cst_equal (step, integer_minus_one_node)))
965 return gfc_trans_simple_do (code, &block, dovar, from, to, step);
c0b29099 966
5d148c08
FXC
967 pos_step = fold_build2 (GT_EXPR, boolean_type_node, step,
968 fold_convert (type, integer_zero_node));
6de9cd9a 969
8d5cfa27 970 if (TREE_CODE (type) == INTEGER_TYPE)
c0b29099
JJ
971 utype = unsigned_type_for (type);
972 else
973 utype = unsigned_type_for (gfc_array_index_type);
974 countm1 = gfc_create_var (utype, "countm1");
5d148c08 975
c0b29099
JJ
976 /* Cycle and exit statements are implemented with gotos. */
977 cycle_label = gfc_build_label_decl (NULL_TREE);
978 exit_label = gfc_build_label_decl (NULL_TREE);
979 TREE_USED (exit_label) = 1;
980
981 /* Initialize the DO variable: dovar = from. */
982 gfc_add_modify (&block, dovar, from);
983
33abc845
TB
984 /* Save value for do-tinkering checking. */
985 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
986 {
987 saved_dovar = gfc_create_var (type, ".saved_dovar");
988 gfc_add_modify (&block, saved_dovar, dovar);
989 }
990
c0b29099
JJ
991 /* Initialize loop count and jump to exit label if the loop is empty.
992 This code is executed before we enter the loop body. We generate:
993 if (step > 0)
994 {
995 if (to < from) goto exit_label;
996 countm1 = (to - from) / step;
997 }
998 else
999 {
1000 if (to > from) goto exit_label;
1001 countm1 = (from - to) / -step;
1002 } */
1003 if (TREE_CODE (type) == INTEGER_TYPE)
1004 {
1005 tree pos, neg;
5d148c08 1006
c0b29099
JJ
1007 tmp = fold_build2 (LT_EXPR, boolean_type_node, to, from);
1008 pos = fold_build3 (COND_EXPR, void_type_node, tmp,
1009 build1_v (GOTO_EXPR, exit_label),
1010 build_empty_stmt ());
1011 tmp = fold_build2 (MINUS_EXPR, type, to, from);
1012 tmp = fold_convert (utype, tmp);
1013 tmp = fold_build2 (TRUNC_DIV_EXPR, utype, tmp,
1014 fold_convert (utype, step));
1015 tmp = build2 (MODIFY_EXPR, void_type_node, countm1, tmp);
1016 pos = build2 (COMPOUND_EXPR, void_type_node, pos, tmp);
1017
1018 tmp = fold_build2 (GT_EXPR, boolean_type_node, to, from);
1019 neg = fold_build3 (COND_EXPR, void_type_node, tmp,
1020 build1_v (GOTO_EXPR, exit_label),
1021 build_empty_stmt ());
1022 tmp = fold_build2 (MINUS_EXPR, type, from, to);
1023 tmp = fold_convert (utype, tmp);
1024 tmp = fold_build2 (TRUNC_DIV_EXPR, utype, tmp,
1025 fold_convert (utype, fold_build1 (NEGATE_EXPR,
1026 type, step)));
1027 tmp = build2 (MODIFY_EXPR, void_type_node, countm1, tmp);
1028 neg = build2 (COMPOUND_EXPR, void_type_node, neg, tmp);
1029
1030 tmp = fold_build3 (COND_EXPR, void_type_node, pos_step, pos, neg);
1031 gfc_add_expr_to_block (&block, tmp);
8d5cfa27
SK
1032 }
1033 else
1034 {
1035 /* TODO: We could use the same width as the real type.
1036 This would probably cause more problems that it solves
1037 when we implement "long double" types. */
c0b29099 1038
5d148c08 1039 tmp = fold_build2 (MINUS_EXPR, type, to, from);
10c7a96f 1040 tmp = fold_build2 (RDIV_EXPR, type, tmp, step);
5d148c08 1041 tmp = fold_build1 (FIX_TRUNC_EXPR, utype, tmp);
c0b29099
JJ
1042 gfc_add_modify (&block, countm1, tmp);
1043
1044 /* We need a special check for empty loops:
1045 empty = (step > 0 ? to < from : to > from); */
1046 tmp = fold_build3 (COND_EXPR, boolean_type_node, pos_step,
1047 fold_build2 (LT_EXPR, boolean_type_node, to, from),
1048 fold_build2 (GT_EXPR, boolean_type_node, to, from));
1049 /* If the loop is empty, go directly to the exit label. */
1050 tmp = fold_build3 (COND_EXPR, void_type_node, tmp,
1051 build1_v (GOTO_EXPR, exit_label),
1052 build_empty_stmt ());
1053 gfc_add_expr_to_block (&block, tmp);
8d5cfa27 1054 }
5d148c08 1055
6de9cd9a
DN
1056 /* Loop body. */
1057 gfc_start_block (&body);
1058
6de9cd9a
DN
1059 /* Put these labels where they can be found later. We put the
1060 labels in a TREE_LIST node (because TREE_CHAIN is already
1061 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
1062 label in TREE_VALUE (backend_decl). */
1063
1064 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
1065
1066 /* Main loop body. */
1067 tmp = gfc_trans_code (code->block->next);
1068 gfc_add_expr_to_block (&body, tmp);
1069
1070 /* Label for cycle statements (if needed). */
1071 if (TREE_USED (cycle_label))
1072 {
1073 tmp = build1_v (LABEL_EXPR, cycle_label);
1074 gfc_add_expr_to_block (&body, tmp);
1075 }
1076
33abc845
TB
1077 /* Check whether someone has modified the loop variable. */
1078 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1079 {
1080 tmp = fold_build2 (NE_EXPR, boolean_type_node, dovar, saved_dovar);
1081 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1082 "Loop variable has been modified");
1083 }
1084
244974bd 1085 /* Increment the loop variable. */
44855d8c 1086 tmp = fold_build2 (PLUS_EXPR, type, dovar, step);
726a989a 1087 gfc_add_modify (&body, dovar, tmp);
244974bd 1088
33abc845
TB
1089 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1090 gfc_add_modify (&body, saved_dovar, dovar);
1091
5d148c08
FXC
1092 /* End with the loop condition. Loop until countm1 == 0. */
1093 cond = fold_build2 (EQ_EXPR, boolean_type_node, countm1,
1094 build_int_cst (utype, 0));
1095 tmp = build1_v (GOTO_EXPR, exit_label);
1096 tmp = fold_build3 (COND_EXPR, void_type_node,
1097 cond, tmp, build_empty_stmt ());
1098 gfc_add_expr_to_block (&body, tmp);
1099
6de9cd9a 1100 /* Decrement the loop count. */
44855d8c 1101 tmp = fold_build2 (MINUS_EXPR, utype, countm1, build_int_cst (utype, 1));
726a989a 1102 gfc_add_modify (&body, countm1, tmp);
6de9cd9a
DN
1103
1104 /* End of loop body. */
1105 tmp = gfc_finish_block (&body);
1106
1107 /* The for loop itself. */
923ab88c 1108 tmp = build1_v (LOOP_EXPR, tmp);
6de9cd9a
DN
1109 gfc_add_expr_to_block (&block, tmp);
1110
1111 /* Add the exit label. */
1112 tmp = build1_v (LABEL_EXPR, exit_label);
1113 gfc_add_expr_to_block (&block, tmp);
1114
1115 return gfc_finish_block (&block);
1116}
1117
1118
1119/* Translate the DO WHILE construct.
1120
1121 We translate
1122
1123 DO WHILE (cond)
1124 body
1125 END DO
1126
1127 to:
1128
1129 for ( ; ; )
1130 {
1131 pre_cond;
1132 if (! cond) goto exit_label;
1133 body;
1134cycle_label:
1135 }
1136exit_label:
1137
1138 Because the evaluation of the exit condition `cond' may have side
1139 effects, we can't do much for empty loop bodies. The backend optimizers
1140 should be smart enough to eliminate any dead loops. */
1141
1142tree
1143gfc_trans_do_while (gfc_code * code)
1144{
1145 gfc_se cond;
1146 tree tmp;
1147 tree cycle_label;
1148 tree exit_label;
1149 stmtblock_t block;
1150
1151 /* Everything we build here is part of the loop body. */
1152 gfc_start_block (&block);
1153
1154 /* Cycle and exit statements are implemented with gotos. */
1155 cycle_label = gfc_build_label_decl (NULL_TREE);
1156 exit_label = gfc_build_label_decl (NULL_TREE);
1157
1158 /* Put the labels where they can be found later. See gfc_trans_do(). */
1159 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
1160
1161 /* Create a GIMPLE version of the exit condition. */
1162 gfc_init_se (&cond, NULL);
1163 gfc_conv_expr_val (&cond, code->expr);
1164 gfc_add_block_to_block (&block, &cond.pre);
10c7a96f 1165 cond.expr = fold_build1 (TRUTH_NOT_EXPR, boolean_type_node, cond.expr);
6de9cd9a
DN
1166
1167 /* Build "IF (! cond) GOTO exit_label". */
1168 tmp = build1_v (GOTO_EXPR, exit_label);
1169 TREE_USED (exit_label) = 1;
61ead135
RG
1170 tmp = fold_build3 (COND_EXPR, void_type_node,
1171 cond.expr, tmp, build_empty_stmt ());
6de9cd9a
DN
1172 gfc_add_expr_to_block (&block, tmp);
1173
1174 /* The main body of the loop. */
1175 tmp = gfc_trans_code (code->block->next);
1176 gfc_add_expr_to_block (&block, tmp);
1177
1178 /* Label for cycle statements (if needed). */
1179 if (TREE_USED (cycle_label))
1180 {
1181 tmp = build1_v (LABEL_EXPR, cycle_label);
1182 gfc_add_expr_to_block (&block, tmp);
1183 }
1184
1185 /* End of loop body. */
1186 tmp = gfc_finish_block (&block);
1187
1188 gfc_init_block (&block);
1189 /* Build the loop. */
923ab88c 1190 tmp = build1_v (LOOP_EXPR, tmp);
6de9cd9a
DN
1191 gfc_add_expr_to_block (&block, tmp);
1192
1193 /* Add the exit label. */
1194 tmp = build1_v (LABEL_EXPR, exit_label);
1195 gfc_add_expr_to_block (&block, tmp);
1196
1197 return gfc_finish_block (&block);
1198}
1199
1200
1201/* Translate the SELECT CASE construct for INTEGER case expressions,
1202 without killing all potential optimizations. The problem is that
1203 Fortran allows unbounded cases, but the back-end does not, so we
1204 need to intercept those before we enter the equivalent SWITCH_EXPR
1205 we can build.
1206
1207 For example, we translate this,
1208
1209 SELECT CASE (expr)
1210 CASE (:100,101,105:115)
1211 block_1
1212 CASE (190:199,200:)
1213 block_2
1214 CASE (300)
1215 block_3
1216 CASE DEFAULT
1217 block_4
1218 END SELECT
1219
1220 to the GENERIC equivalent,
1221
1222 switch (expr)
1223 {
1224 case (minimum value for typeof(expr) ... 100:
1225 case 101:
1226 case 105 ... 114:
1227 block1:
1228 goto end_label;
1229
1230 case 200 ... (maximum value for typeof(expr):
1231 case 190 ... 199:
1232 block2;
1233 goto end_label;
1234
1235 case 300:
1236 block_3;
1237 goto end_label;
1238
1239 default:
1240 block_4;
1241 goto end_label;
1242 }
1243
1244 end_label: */
1245
1246static tree
1247gfc_trans_integer_select (gfc_code * code)
1248{
1249 gfc_code *c;
1250 gfc_case *cp;
1251 tree end_label;
1252 tree tmp;
1253 gfc_se se;
1254 stmtblock_t block;
1255 stmtblock_t body;
1256
1257 gfc_start_block (&block);
1258
1259 /* Calculate the switch expression. */
1260 gfc_init_se (&se, NULL);
1261 gfc_conv_expr_val (&se, code->expr);
1262 gfc_add_block_to_block (&block, &se.pre);
1263
1264 end_label = gfc_build_label_decl (NULL_TREE);
1265
1266 gfc_init_block (&body);
1267
1268 for (c = code->block; c; c = c->block)
1269 {
1270 for (cp = c->ext.case_list; cp; cp = cp->next)
1271 {
1272 tree low, high;
1273 tree label;
1274
1275 /* Assume it's the default case. */
1276 low = high = NULL_TREE;
1277
1278 if (cp->low)
1279 {
20585ad6
BM
1280 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1281 cp->low->ts.kind);
6de9cd9a
DN
1282
1283 /* If there's only a lower bound, set the high bound to the
1284 maximum value of the case expression. */
1285 if (!cp->high)
1286 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1287 }
1288
1289 if (cp->high)
1290 {
1291 /* Three cases are possible here:
1292
1293 1) There is no lower bound, e.g. CASE (:N).
1294 2) There is a lower bound .NE. high bound, that is
1295 a case range, e.g. CASE (N:M) where M>N (we make
1296 sure that M>N during type resolution).
1297 3) There is a lower bound, and it has the same value
1298 as the high bound, e.g. CASE (N:N). This is our
1299 internal representation of CASE(N).
1300
1301 In the first and second case, we need to set a value for
e2ae1407 1302 high. In the third case, we don't because the GCC middle
6de9cd9a
DN
1303 end represents a single case value by just letting high be
1304 a NULL_TREE. We can't do that because we need to be able
1305 to represent unbounded cases. */
1306
1307 if (!cp->low
1308 || (cp->low
1309 && mpz_cmp (cp->low->value.integer,
1310 cp->high->value.integer) != 0))
20585ad6
BM
1311 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1312 cp->high->ts.kind);
6de9cd9a
DN
1313
1314 /* Unbounded case. */
1315 if (!cp->low)
1316 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1317 }
1318
1319 /* Build a label. */
c006df4e 1320 label = gfc_build_label_decl (NULL_TREE);
6de9cd9a
DN
1321
1322 /* Add this case label.
1323 Add parameter 'label', make it match GCC backend. */
44855d8c
TS
1324 tmp = fold_build3 (CASE_LABEL_EXPR, void_type_node,
1325 low, high, label);
6de9cd9a
DN
1326 gfc_add_expr_to_block (&body, tmp);
1327 }
1328
1329 /* Add the statements for this case. */
1330 tmp = gfc_trans_code (c->next);
1331 gfc_add_expr_to_block (&body, tmp);
1332
1333 /* Break to the end of the construct. */
1334 tmp = build1_v (GOTO_EXPR, end_label);
1335 gfc_add_expr_to_block (&body, tmp);
1336 }
1337
1338 tmp = gfc_finish_block (&body);
923ab88c 1339 tmp = build3_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE);
6de9cd9a
DN
1340 gfc_add_expr_to_block (&block, tmp);
1341
1342 tmp = build1_v (LABEL_EXPR, end_label);
1343 gfc_add_expr_to_block (&block, tmp);
1344
1345 return gfc_finish_block (&block);
1346}
1347
1348
1349/* Translate the SELECT CASE construct for LOGICAL case expressions.
1350
1351 There are only two cases possible here, even though the standard
1352 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
1353 .FALSE., and DEFAULT.
1354
1355 We never generate more than two blocks here. Instead, we always
1356 try to eliminate the DEFAULT case. This way, we can translate this
1357 kind of SELECT construct to a simple
1358
1359 if {} else {};
1360
1361 expression in GENERIC. */
1362
1363static tree
1364gfc_trans_logical_select (gfc_code * code)
1365{
1366 gfc_code *c;
1367 gfc_code *t, *f, *d;
1368 gfc_case *cp;
1369 gfc_se se;
1370 stmtblock_t block;
1371
1372 /* Assume we don't have any cases at all. */
1373 t = f = d = NULL;
1374
1375 /* Now see which ones we actually do have. We can have at most two
1376 cases in a single case list: one for .TRUE. and one for .FALSE.
1377 The default case is always separate. If the cases for .TRUE. and
1378 .FALSE. are in the same case list, the block for that case list
1379 always executed, and we don't generate code a COND_EXPR. */
1380 for (c = code->block; c; c = c->block)
1381 {
1382 for (cp = c->ext.case_list; cp; cp = cp->next)
1383 {
1384 if (cp->low)
1385 {
1386 if (cp->low->value.logical == 0) /* .FALSE. */
1387 f = c;
1388 else /* if (cp->value.logical != 0), thus .TRUE. */
1389 t = c;
1390 }
1391 else
1392 d = c;
1393 }
1394 }
1395
1396 /* Start a new block. */
1397 gfc_start_block (&block);
1398
1399 /* Calculate the switch expression. We always need to do this
1400 because it may have side effects. */
1401 gfc_init_se (&se, NULL);
1402 gfc_conv_expr_val (&se, code->expr);
1403 gfc_add_block_to_block (&block, &se.pre);
1404
1405 if (t == f && t != NULL)
1406 {
1407 /* Cases for .TRUE. and .FALSE. are in the same block. Just
1408 translate the code for these cases, append it to the current
1409 block. */
1410 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
1411 }
1412 else
1413 {
61ead135 1414 tree true_tree, false_tree, stmt;
6de9cd9a
DN
1415
1416 true_tree = build_empty_stmt ();
1417 false_tree = build_empty_stmt ();
1418
1419 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
1420 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
1421 make the missing case the default case. */
1422 if (t != NULL && f != NULL)
1423 d = NULL;
1424 else if (d != NULL)
1425 {
1426 if (t == NULL)
1427 t = d;
1428 else
1429 f = d;
1430 }
1431
1432 /* Translate the code for each of these blocks, and append it to
1433 the current block. */
1434 if (t != NULL)
1435 true_tree = gfc_trans_code (t->next);
1436
1437 if (f != NULL)
1438 false_tree = gfc_trans_code (f->next);
1439
61ead135
RG
1440 stmt = fold_build3 (COND_EXPR, void_type_node, se.expr,
1441 true_tree, false_tree);
1442 gfc_add_expr_to_block (&block, stmt);
6de9cd9a
DN
1443 }
1444
1445 return gfc_finish_block (&block);
1446}
1447
1448
1449/* Translate the SELECT CASE construct for CHARACTER case expressions.
1450 Instead of generating compares and jumps, it is far simpler to
1451 generate a data structure describing the cases in order and call a
1452 library subroutine that locates the right case.
1453 This is particularly true because this is the only case where we
1454 might have to dispose of a temporary.
1455 The library subroutine returns a pointer to jump to or NULL if no
1456 branches are to be taken. */
1457
1458static tree
1459gfc_trans_character_select (gfc_code *code)
1460{
d393bbd7 1461 tree init, node, end_label, tmp, type, case_num, label, fndecl;
6de9cd9a
DN
1462 stmtblock_t block, body;
1463 gfc_case *cp, *d;
1464 gfc_code *c;
1465 gfc_se se;
d393bbd7
FXC
1466 int n, k;
1467
1468 /* The jump table types are stored in static variables to avoid
1469 constructing them from scratch every single time. */
1470 static tree select_struct[2];
1471 static tree ss_string1[2], ss_string1_len[2];
1472 static tree ss_string2[2], ss_string2_len[2];
1473 static tree ss_target[2];
1474
1475 tree pchartype = gfc_get_pchar_type (code->expr->ts.kind);
6de9cd9a 1476
d393bbd7
FXC
1477 if (code->expr->ts.kind == 1)
1478 k = 0;
1479 else if (code->expr->ts.kind == 4)
1480 k = 1;
1481 else
1482 gcc_unreachable ();
6de9cd9a 1483
d393bbd7 1484 if (select_struct[k] == NULL)
6de9cd9a 1485 {
d393bbd7 1486 select_struct[k] = make_node (RECORD_TYPE);
e2cad04b 1487
d393bbd7
FXC
1488 if (code->expr->ts.kind == 1)
1489 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
1490 else if (code->expr->ts.kind == 4)
1491 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
1492 else
1493 gcc_unreachable ();
6de9cd9a
DN
1494
1495#undef ADD_FIELD
d393bbd7
FXC
1496#define ADD_FIELD(NAME, TYPE) \
1497 ss_##NAME[k] = gfc_add_field_to_struct \
1498 (&(TYPE_FIELDS (select_struct[k])), select_struct[k], \
6de9cd9a
DN
1499 get_identifier (stringize(NAME)), TYPE)
1500
d393bbd7
FXC
1501 ADD_FIELD (string1, pchartype);
1502 ADD_FIELD (string1_len, gfc_charlen_type_node);
6de9cd9a 1503
d393bbd7
FXC
1504 ADD_FIELD (string2, pchartype);
1505 ADD_FIELD (string2_len, gfc_charlen_type_node);
6de9cd9a 1506
dd52ecb0 1507 ADD_FIELD (target, integer_type_node);
6de9cd9a
DN
1508#undef ADD_FIELD
1509
d393bbd7 1510 gfc_finish_type (select_struct[k]);
6de9cd9a
DN
1511 }
1512
1513 cp = code->block->ext.case_list;
1514 while (cp->left != NULL)
1515 cp = cp->left;
1516
1517 n = 0;
1518 for (d = cp; d; d = d->right)
1519 d->n = n++;
1520
6de9cd9a
DN
1521 end_label = gfc_build_label_decl (NULL_TREE);
1522
1523 /* Generate the body */
1524 gfc_start_block (&block);
1525 gfc_init_block (&body);
1526
1527 for (c = code->block; c; c = c->block)
1528 {
1529 for (d = c->ext.case_list; d; d = d->next)
1530 {
2b8327ce 1531 label = gfc_build_label_decl (NULL_TREE);
44855d8c
TS
1532 tmp = fold_build3 (CASE_LABEL_EXPR, void_type_node,
1533 build_int_cst (NULL_TREE, d->n),
1534 build_int_cst (NULL_TREE, d->n), label);
6de9cd9a
DN
1535 gfc_add_expr_to_block (&body, tmp);
1536 }
1537
1538 tmp = gfc_trans_code (c->next);
1539 gfc_add_expr_to_block (&body, tmp);
1540
923ab88c 1541 tmp = build1_v (GOTO_EXPR, end_label);
6de9cd9a
DN
1542 gfc_add_expr_to_block (&body, tmp);
1543 }
1544
1545 /* Generate the structure describing the branches */
1546 init = NULL_TREE;
6de9cd9a 1547
2b8327ce 1548 for(d = cp; d; d = d->right)
6de9cd9a
DN
1549 {
1550 node = NULL_TREE;
1551
1552 gfc_init_se (&se, NULL);
1553
1554 if (d->low == NULL)
1555 {
d393bbd7
FXC
1556 node = tree_cons (ss_string1[k], null_pointer_node, node);
1557 node = tree_cons (ss_string1_len[k], integer_zero_node, node);
6de9cd9a
DN
1558 }
1559 else
1560 {
1561 gfc_conv_expr_reference (&se, d->low);
1562
d393bbd7
FXC
1563 node = tree_cons (ss_string1[k], se.expr, node);
1564 node = tree_cons (ss_string1_len[k], se.string_length, node);
6de9cd9a
DN
1565 }
1566
1567 if (d->high == NULL)
1568 {
d393bbd7
FXC
1569 node = tree_cons (ss_string2[k], null_pointer_node, node);
1570 node = tree_cons (ss_string2_len[k], integer_zero_node, node);
6de9cd9a
DN
1571 }
1572 else
1573 {
1574 gfc_init_se (&se, NULL);
1575 gfc_conv_expr_reference (&se, d->high);
1576
d393bbd7
FXC
1577 node = tree_cons (ss_string2[k], se.expr, node);
1578 node = tree_cons (ss_string2_len[k], se.string_length, node);
6de9cd9a
DN
1579 }
1580
d393bbd7 1581 node = tree_cons (ss_target[k], build_int_cst (integer_type_node, d->n),
2b8327ce 1582 node);
6de9cd9a 1583
d393bbd7 1584 tmp = build_constructor_from_list (select_struct[k], nreverse (node));
6de9cd9a
DN
1585 init = tree_cons (NULL_TREE, tmp, init);
1586 }
1587
d393bbd7
FXC
1588 type = build_array_type (select_struct[k],
1589 build_index_type (build_int_cst (NULL_TREE, n-1)));
6de9cd9a 1590
4038c495 1591 init = build_constructor_from_list (type, nreverse(init));
6de9cd9a 1592 TREE_CONSTANT (init) = 1;
6de9cd9a
DN
1593 TREE_STATIC (init) = 1;
1594 /* Create a static variable to hold the jump table. */
1595 tmp = gfc_create_var (type, "jumptable");
1596 TREE_CONSTANT (tmp) = 1;
6de9cd9a 1597 TREE_STATIC (tmp) = 1;
0f0707d1 1598 TREE_READONLY (tmp) = 1;
6de9cd9a
DN
1599 DECL_INITIAL (tmp) = init;
1600 init = tmp;
1601
5039610b 1602 /* Build the library call */
6de9cd9a 1603 init = gfc_build_addr_expr (pvoid_type_node, init);
6de9cd9a
DN
1604
1605 gfc_init_se (&se, NULL);
1606 gfc_conv_expr_reference (&se, code->expr);
1607
6de9cd9a
DN
1608 gfc_add_block_to_block (&block, &se.pre);
1609
d393bbd7
FXC
1610 if (code->expr->ts.kind == 1)
1611 fndecl = gfor_fndecl_select_string;
1612 else if (code->expr->ts.kind == 4)
1613 fndecl = gfor_fndecl_select_string_char4;
1614 else
1615 gcc_unreachable ();
1616
1617 tmp = build_call_expr (fndecl, 4, init, build_int_cst (NULL_TREE, n),
1618 se.expr, se.string_length);
dd52ecb0 1619 case_num = gfc_create_var (integer_type_node, "case_num");
726a989a 1620 gfc_add_modify (&block, case_num, tmp);
dc6c7714
PT
1621
1622 gfc_add_block_to_block (&block, &se.post);
1623
6de9cd9a 1624 tmp = gfc_finish_block (&body);
2b8327ce 1625 tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE);
6de9cd9a 1626 gfc_add_expr_to_block (&block, tmp);
2b8327ce 1627
923ab88c 1628 tmp = build1_v (LABEL_EXPR, end_label);
6de9cd9a
DN
1629 gfc_add_expr_to_block (&block, tmp);
1630
6de9cd9a
DN
1631 return gfc_finish_block (&block);
1632}
1633
1634
1635/* Translate the three variants of the SELECT CASE construct.
1636
1637 SELECT CASEs with INTEGER case expressions can be translated to an
1638 equivalent GENERIC switch statement, and for LOGICAL case
1639 expressions we build one or two if-else compares.
1640
1641 SELECT CASEs with CHARACTER case expressions are a whole different
1642 story, because they don't exist in GENERIC. So we sort them and
1643 do a binary search at runtime.
1644
1645 Fortran has no BREAK statement, and it does not allow jumps from
1646 one case block to another. That makes things a lot easier for
1647 the optimizers. */
1648
1649tree
1650gfc_trans_select (gfc_code * code)
1651{
6e45f57b 1652 gcc_assert (code && code->expr);
6de9cd9a
DN
1653
1654 /* Empty SELECT constructs are legal. */
1655 if (code->block == NULL)
1656 return build_empty_stmt ();
1657
1658 /* Select the correct translation function. */
1659 switch (code->expr->ts.type)
1660 {
1661 case BT_LOGICAL: return gfc_trans_logical_select (code);
1662 case BT_INTEGER: return gfc_trans_integer_select (code);
1663 case BT_CHARACTER: return gfc_trans_character_select (code);
1664 default:
1665 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
1666 /* Not reached */
1667 }
1668}
1669
1670
640670c7
PT
1671/* Traversal function to substitute a replacement symtree if the symbol
1672 in the expression is the same as that passed. f == 2 signals that
1673 that variable itself is not to be checked - only the references.
1674 This group of functions is used when the variable expression in a
1675 FORALL assignment has internal references. For example:
1676 FORALL (i = 1:4) p(p(i)) = i
1677 The only recourse here is to store a copy of 'p' for the index
1678 expression. */
1679
1680static gfc_symtree *new_symtree;
1681static gfc_symtree *old_symtree;
1682
1683static bool
1684forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
1685{
908a2235
PT
1686 if (expr->expr_type != EXPR_VARIABLE)
1687 return false;
640670c7
PT
1688
1689 if (*f == 2)
1690 *f = 1;
1691 else if (expr->symtree->n.sym == sym)
1692 expr->symtree = new_symtree;
1693
1694 return false;
1695}
1696
1697static void
1698forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
1699{
1700 gfc_traverse_expr (e, sym, forall_replace, f);
1701}
1702
1703static bool
1704forall_restore (gfc_expr *expr,
1705 gfc_symbol *sym ATTRIBUTE_UNUSED,
1706 int *f ATTRIBUTE_UNUSED)
1707{
908a2235
PT
1708 if (expr->expr_type != EXPR_VARIABLE)
1709 return false;
640670c7
PT
1710
1711 if (expr->symtree == new_symtree)
1712 expr->symtree = old_symtree;
1713
1714 return false;
1715}
1716
1717static void
1718forall_restore_symtree (gfc_expr *e)
1719{
1720 gfc_traverse_expr (e, NULL, forall_restore, 0);
1721}
1722
1723static void
1724forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
1725{
1726 gfc_se tse;
1727 gfc_se rse;
1728 gfc_expr *e;
1729 gfc_symbol *new_sym;
1730 gfc_symbol *old_sym;
1731 gfc_symtree *root;
1732 tree tmp;
1733
1734 /* Build a copy of the lvalue. */
1735 old_symtree = c->expr->symtree;
1736 old_sym = old_symtree->n.sym;
1737 e = gfc_lval_expr_from_sym (old_sym);
1738 if (old_sym->attr.dimension)
1739 {
1740 gfc_init_se (&tse, NULL);
1741 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN);
1742 gfc_add_block_to_block (pre, &tse.pre);
1743 gfc_add_block_to_block (post, &tse.post);
1744 tse.expr = build_fold_indirect_ref (tse.expr);
1745
1746 if (e->ts.type != BT_CHARACTER)
1747 {
1748 /* Use the variable offset for the temporary. */
1749 tmp = gfc_conv_descriptor_offset (tse.expr);
726a989a 1750 gfc_add_modify (pre, tmp,
640670c7
PT
1751 gfc_conv_array_offset (old_sym->backend_decl));
1752 }
1753 }
1754 else
1755 {
1756 gfc_init_se (&tse, NULL);
1757 gfc_init_se (&rse, NULL);
1758 gfc_conv_expr (&rse, e);
1759 if (e->ts.type == BT_CHARACTER)
1760 {
1761 tse.string_length = rse.string_length;
1762 tmp = gfc_get_character_type_len (gfc_default_character_kind,
1763 tse.string_length);
1764 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
1765 rse.string_length);
1766 gfc_add_block_to_block (pre, &tse.pre);
1767 gfc_add_block_to_block (post, &tse.post);
1768 }
1769 else
1770 {
1771 tmp = gfc_typenode_for_spec (&e->ts);
1772 tse.expr = gfc_create_var (tmp, "temp");
1773 }
1774
1775 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
1776 e->expr_type == EXPR_VARIABLE);
1777 gfc_add_expr_to_block (pre, tmp);
1778 }
1779 gfc_free_expr (e);
1780
1781 /* Create a new symbol to represent the lvalue. */
1782 new_sym = gfc_new_symbol (old_sym->name, NULL);
1783 new_sym->ts = old_sym->ts;
1784 new_sym->attr.referenced = 1;
59e36b72 1785 new_sym->attr.temporary = 1;
640670c7
PT
1786 new_sym->attr.dimension = old_sym->attr.dimension;
1787 new_sym->attr.flavor = old_sym->attr.flavor;
1788
1789 /* Use the temporary as the backend_decl. */
1790 new_sym->backend_decl = tse.expr;
1791
1792 /* Create a fake symtree for it. */
1793 root = NULL;
1794 new_symtree = gfc_new_symtree (&root, old_sym->name);
1795 new_symtree->n.sym = new_sym;
1796 gcc_assert (new_symtree == root);
1797
1798 /* Go through the expression reference replacing the old_symtree
1799 with the new. */
1800 forall_replace_symtree (c->expr, old_sym, 2);
1801
1802 /* Now we have made this temporary, we might as well use it for
1803 the right hand side. */
1804 forall_replace_symtree (c->expr2, old_sym, 1);
1805}
1806
1807
1808/* Handles dependencies in forall assignments. */
1809static int
1810check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
1811{
1812 gfc_ref *lref;
1813 gfc_ref *rref;
1814 int need_temp;
1815 gfc_symbol *lsym;
1816
1817 lsym = c->expr->symtree->n.sym;
1818 need_temp = gfc_check_dependency (c->expr, c->expr2, 0);
1819
1820 /* Now check for dependencies within the 'variable'
1821 expression itself. These are treated by making a complete
1822 copy of variable and changing all the references to it
1823 point to the copy instead. Note that the shallow copy of
1824 the variable will not suffice for derived types with
1825 pointer components. We therefore leave these to their
1826 own devices. */
1827 if (lsym->ts.type == BT_DERIVED
1828 && lsym->ts.derived->attr.pointer_comp)
1829 return need_temp;
1830
1831 new_symtree = NULL;
1832 if (find_forall_index (c->expr, lsym, 2) == SUCCESS)
1833 {
1834 forall_make_variable_temp (c, pre, post);
1835 need_temp = 0;
1836 }
1837
1838 /* Substrings with dependencies are treated in the same
1839 way. */
1840 if (c->expr->ts.type == BT_CHARACTER
1841 && c->expr->ref
1842 && c->expr2->expr_type == EXPR_VARIABLE
1843 && lsym == c->expr2->symtree->n.sym)
1844 {
1845 for (lref = c->expr->ref; lref; lref = lref->next)
1846 if (lref->type == REF_SUBSTRING)
1847 break;
1848 for (rref = c->expr2->ref; rref; rref = rref->next)
1849 if (rref->type == REF_SUBSTRING)
1850 break;
1851
1852 if (rref && lref
1853 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
1854 {
1855 forall_make_variable_temp (c, pre, post);
1856 need_temp = 0;
1857 }
1858 }
1859 return need_temp;
1860}
1861
1862
1863static void
1864cleanup_forall_symtrees (gfc_code *c)
1865{
1866 forall_restore_symtree (c->expr);
1867 forall_restore_symtree (c->expr2);
1868 gfc_free (new_symtree->n.sym);
1869 gfc_free (new_symtree);
1870}
1871
1872
bfcabc6c
RS
1873/* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
1874 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
1875 indicates whether we should generate code to test the FORALLs mask
1876 array. OUTER is the loop header to be used for initializing mask
1877 indices.
1878
1879 The generated loop format is:
6de9cd9a
DN
1880 count = (end - start + step) / step
1881 loopvar = start
1882 while (1)
1883 {
1884 if (count <=0 )
1885 goto end_of_loop
1886 <body>
1887 loopvar += step
1888 count --
1889 }
1890 end_of_loop: */
1891
1892static tree
bfcabc6c
RS
1893gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
1894 int mask_flag, stmtblock_t *outer)
6de9cd9a 1895{
bfcabc6c 1896 int n, nvar;
6de9cd9a
DN
1897 tree tmp;
1898 tree cond;
1899 stmtblock_t block;
1900 tree exit_label;
1901 tree count;
fcf3be37 1902 tree var, start, end, step;
6de9cd9a
DN
1903 iter_info *iter;
1904
bfcabc6c
RS
1905 /* Initialize the mask index outside the FORALL nest. */
1906 if (mask_flag && forall_tmp->mask)
726a989a 1907 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
bfcabc6c 1908
6de9cd9a 1909 iter = forall_tmp->this_loop;
bfcabc6c 1910 nvar = forall_tmp->nvar;
6de9cd9a
DN
1911 for (n = 0; n < nvar; n++)
1912 {
1913 var = iter->var;
1914 start = iter->start;
1915 end = iter->end;
1916 step = iter->step;
1917
1918 exit_label = gfc_build_label_decl (NULL_TREE);
1919 TREE_USED (exit_label) = 1;
1920
1921 /* The loop counter. */
1922 count = gfc_create_var (TREE_TYPE (var), "count");
1923
1924 /* The body of the loop. */
1925 gfc_init_block (&block);
1926
1927 /* The exit condition. */
61ead135
RG
1928 cond = fold_build2 (LE_EXPR, boolean_type_node,
1929 count, build_int_cst (TREE_TYPE (count), 0));
6de9cd9a 1930 tmp = build1_v (GOTO_EXPR, exit_label);
61ead135
RG
1931 tmp = fold_build3 (COND_EXPR, void_type_node,
1932 cond, tmp, build_empty_stmt ());
6de9cd9a
DN
1933 gfc_add_expr_to_block (&block, tmp);
1934
1935 /* The main loop body. */
1936 gfc_add_expr_to_block (&block, body);
1937
1938 /* Increment the loop variable. */
44855d8c 1939 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (var), var, step);
726a989a 1940 gfc_add_modify (&block, var, tmp);
6de9cd9a 1941
a8e12e4d
TS
1942 /* Advance to the next mask element. Only do this for the
1943 innermost loop. */
fcf3be37
JJ
1944 if (n == 0 && mask_flag && forall_tmp->mask)
1945 {
1946 tree maskindex = forall_tmp->maskindex;
44855d8c
TS
1947 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1948 maskindex, gfc_index_one_node);
726a989a 1949 gfc_add_modify (&block, maskindex, tmp);
fcf3be37
JJ
1950 }
1951
6de9cd9a 1952 /* Decrement the loop counter. */
44855d8c
TS
1953 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), count,
1954 build_int_cst (TREE_TYPE (var), 1));
726a989a 1955 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
1956
1957 body = gfc_finish_block (&block);
1958
1959 /* Loop var initialization. */
1960 gfc_init_block (&block);
726a989a 1961 gfc_add_modify (&block, var, start);
6de9cd9a 1962
fcf3be37 1963
6de9cd9a 1964 /* Initialize the loop counter. */
10c7a96f
SB
1965 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), step, start);
1966 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (var), end, tmp);
1967 tmp = fold_build2 (TRUNC_DIV_EXPR, TREE_TYPE (var), tmp, step);
726a989a 1968 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
1969
1970 /* The loop expression. */
923ab88c 1971 tmp = build1_v (LOOP_EXPR, body);
6de9cd9a
DN
1972 gfc_add_expr_to_block (&block, tmp);
1973
1974 /* The exit label. */
1975 tmp = build1_v (LABEL_EXPR, exit_label);
1976 gfc_add_expr_to_block (&block, tmp);
1977
1978 body = gfc_finish_block (&block);
1979 iter = iter->next;
1980 }
1981 return body;
1982}
1983
1984
bfcabc6c
RS
1985/* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
1986 is nonzero, the body is controlled by all masks in the forall nest.
1987 Otherwise, the innermost loop is not controlled by it's mask. This
1988 is used for initializing that mask. */
6de9cd9a
DN
1989
1990static tree
1991gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
bfcabc6c 1992 int mask_flag)
6de9cd9a
DN
1993{
1994 tree tmp;
bfcabc6c 1995 stmtblock_t header;
6de9cd9a 1996 forall_info *forall_tmp;
bfcabc6c
RS
1997 tree mask, maskindex;
1998
1999 gfc_start_block (&header);
6de9cd9a
DN
2000
2001 forall_tmp = nested_forall_info;
bfcabc6c 2002 while (forall_tmp != NULL)
6de9cd9a 2003 {
bfcabc6c
RS
2004 /* Generate body with masks' control. */
2005 if (mask_flag)
6de9cd9a 2006 {
bfcabc6c
RS
2007 mask = forall_tmp->mask;
2008 maskindex = forall_tmp->maskindex;
6de9cd9a 2009
bfcabc6c
RS
2010 /* If a mask was specified make the assignment conditional. */
2011 if (mask)
2012 {
1d6b7f39 2013 tmp = gfc_build_array_ref (mask, maskindex, NULL);
bfcabc6c 2014 body = build3_v (COND_EXPR, tmp, body, build_empty_stmt ());
6de9cd9a 2015 }
6de9cd9a 2016 }
bfcabc6c 2017 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
e8d366ec 2018 forall_tmp = forall_tmp->prev_nest;
bfcabc6c 2019 mask_flag = 1;
6de9cd9a
DN
2020 }
2021
bfcabc6c
RS
2022 gfc_add_expr_to_block (&header, body);
2023 return gfc_finish_block (&header);
6de9cd9a
DN
2024}
2025
2026
2027/* Allocate data for holding a temporary array. Returns either a local
2028 temporary array or a pointer variable. */
2029
2030static tree
2031gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2032 tree elem_type)
2033{
2034 tree tmpvar;
2035 tree type;
2036 tree tmp;
6de9cd9a
DN
2037
2038 if (INTEGER_CST_P (size))
2039 {
10c7a96f
SB
2040 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
2041 gfc_index_one_node);
6de9cd9a
DN
2042 }
2043 else
2044 tmp = NULL_TREE;
2045
7ab92584 2046 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
6de9cd9a
DN
2047 type = build_array_type (elem_type, type);
2048 if (gfc_can_put_var_on_stack (bytesize))
2049 {
6e45f57b 2050 gcc_assert (INTEGER_CST_P (size));
6de9cd9a
DN
2051 tmpvar = gfc_create_var (type, "temp");
2052 *pdata = NULL_TREE;
2053 }
2054 else
2055 {
2056 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2057 *pdata = convert (pvoid_type_node, tmpvar);
2058
1529b8d9 2059 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
726a989a 2060 gfc_add_modify (pblock, tmpvar, tmp);
6de9cd9a
DN
2061 }
2062 return tmpvar;
2063}
2064
2065
2066/* Generate codes to copy the temporary to the actual lhs. */
2067
2068static tree
8de1f441 2069generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
011daa76 2070 tree count1, tree wheremask, bool invert)
6de9cd9a
DN
2071{
2072 gfc_ss *lss;
2073 gfc_se lse, rse;
2074 stmtblock_t block, body;
2075 gfc_loopinfo loop1;
011daa76 2076 tree tmp;
6de9cd9a
DN
2077 tree wheremaskexpr;
2078
2079 /* Walk the lhs. */
2080 lss = gfc_walk_expr (expr);
2081
2082 if (lss == gfc_ss_terminator)
2083 {
2084 gfc_start_block (&block);
2085
2086 gfc_init_se (&lse, NULL);
2087
2088 /* Translate the expression. */
2089 gfc_conv_expr (&lse, expr);
2090
2091 /* Form the expression for the temporary. */
1d6b7f39 2092 tmp = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2093
2094 /* Use the scalar assignment as is. */
2095 gfc_add_block_to_block (&block, &lse.pre);
726a989a 2096 gfc_add_modify (&block, lse.expr, tmp);
6de9cd9a
DN
2097 gfc_add_block_to_block (&block, &lse.post);
2098
2099 /* Increment the count1. */
8de1f441
JJ
2100 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
2101 gfc_index_one_node);
726a989a 2102 gfc_add_modify (&block, count1, tmp);
8de1f441 2103
6de9cd9a
DN
2104 tmp = gfc_finish_block (&block);
2105 }
2106 else
2107 {
2108 gfc_start_block (&block);
2109
2110 gfc_init_loopinfo (&loop1);
2111 gfc_init_se (&rse, NULL);
2112 gfc_init_se (&lse, NULL);
2113
2114 /* Associate the lss with the loop. */
2115 gfc_add_ss_to_loop (&loop1, lss);
2116
2117 /* Calculate the bounds of the scalarization. */
2118 gfc_conv_ss_startstride (&loop1);
2119 /* Setup the scalarizing loops. */
bdfd2ff0 2120 gfc_conv_loop_setup (&loop1, &expr->where);
6de9cd9a
DN
2121
2122 gfc_mark_ss_chain_used (lss, 1);
6de9cd9a
DN
2123
2124 /* Start the scalarized loop body. */
2125 gfc_start_scalarized_body (&loop1, &body);
2126
2127 /* Setup the gfc_se structures. */
2128 gfc_copy_loopinfo_to_se (&lse, &loop1);
2129 lse.ss = lss;
2130
2131 /* Form the expression of the temporary. */
2132 if (lss != gfc_ss_terminator)
1d6b7f39 2133 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2134 /* Translate expr. */
2135 gfc_conv_expr (&lse, expr);
2136
2137 /* Use the scalar assignment. */
5046aff5
PT
2138 rse.string_length = lse.string_length;
2139 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false);
6de9cd9a 2140
011daa76
RS
2141 /* Form the mask expression according to the mask tree list. */
2142 if (wheremask)
2143 {
1d6b7f39 2144 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
011daa76
RS
2145 if (invert)
2146 wheremaskexpr = fold_build1 (TRUTH_NOT_EXPR,
2147 TREE_TYPE (wheremaskexpr),
2148 wheremaskexpr);
2149 tmp = fold_build3 (COND_EXPR, void_type_node,
2150 wheremaskexpr, tmp, build_empty_stmt ());
6de9cd9a
DN
2151 }
2152
2153 gfc_add_expr_to_block (&body, tmp);
2154
8de1f441 2155 /* Increment count1. */
10c7a96f 2156 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
8de1f441 2157 count1, gfc_index_one_node);
726a989a 2158 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
2159
2160 /* Increment count3. */
2161 if (count3)
8de1f441
JJ
2162 {
2163 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
10c7a96f 2164 count3, gfc_index_one_node);
726a989a 2165 gfc_add_modify (&body, count3, tmp);
8de1f441 2166 }
6de9cd9a
DN
2167
2168 /* Generate the copying loops. */
2169 gfc_trans_scalarizing_loops (&loop1, &body);
2170 gfc_add_block_to_block (&block, &loop1.pre);
2171 gfc_add_block_to_block (&block, &loop1.post);
2172 gfc_cleanup_loop (&loop1);
2173
6de9cd9a
DN
2174 tmp = gfc_finish_block (&block);
2175 }
2176 return tmp;
2177}
2178
2179
011daa76
RS
2180/* Generate codes to copy rhs to the temporary. TMP1 is the address of
2181 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
2182 and should not be freed. WHEREMASK is the conditional execution mask
2183 whose sense may be inverted by INVERT. */
6de9cd9a
DN
2184
2185static tree
8de1f441
JJ
2186generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
2187 tree count1, gfc_ss *lss, gfc_ss *rss,
011daa76 2188 tree wheremask, bool invert)
6de9cd9a
DN
2189{
2190 stmtblock_t block, body1;
2191 gfc_loopinfo loop;
2192 gfc_se lse;
2193 gfc_se rse;
011daa76 2194 tree tmp;
6de9cd9a
DN
2195 tree wheremaskexpr;
2196
2197 gfc_start_block (&block);
2198
2199 gfc_init_se (&rse, NULL);
2200 gfc_init_se (&lse, NULL);
2201
2202 if (lss == gfc_ss_terminator)
2203 {
2204 gfc_init_block (&body1);
2205 gfc_conv_expr (&rse, expr2);
1d6b7f39 2206 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2207 }
2208 else
2209 {
1f2959f0 2210 /* Initialize the loop. */
6de9cd9a
DN
2211 gfc_init_loopinfo (&loop);
2212
2213 /* We may need LSS to determine the shape of the expression. */
2214 gfc_add_ss_to_loop (&loop, lss);
2215 gfc_add_ss_to_loop (&loop, rss);
2216
2217 gfc_conv_ss_startstride (&loop);
bdfd2ff0 2218 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
2219
2220 gfc_mark_ss_chain_used (rss, 1);
2221 /* Start the loop body. */
2222 gfc_start_scalarized_body (&loop, &body1);
2223
2224 /* Translate the expression. */
2225 gfc_copy_loopinfo_to_se (&rse, &loop);
2226 rse.ss = rss;
2227 gfc_conv_expr (&rse, expr2);
2228
2229 /* Form the expression of the temporary. */
1d6b7f39 2230 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2231 }
2232
2233 /* Use the scalar assignment. */
5046aff5
PT
2234 lse.string_length = rse.string_length;
2235 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
2236 expr2->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
2237
2238 /* Form the mask expression according to the mask tree list. */
2239 if (wheremask)
2240 {
1d6b7f39 2241 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
011daa76
RS
2242 if (invert)
2243 wheremaskexpr = fold_build1 (TRUTH_NOT_EXPR,
2244 TREE_TYPE (wheremaskexpr),
2245 wheremaskexpr);
61ead135
RG
2246 tmp = fold_build3 (COND_EXPR, void_type_node,
2247 wheremaskexpr, tmp, build_empty_stmt ());
6de9cd9a
DN
2248 }
2249
2250 gfc_add_expr_to_block (&body1, tmp);
2251
2252 if (lss == gfc_ss_terminator)
2253 {
2254 gfc_add_block_to_block (&block, &body1);
8de1f441
JJ
2255
2256 /* Increment count1. */
2257 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
2258 gfc_index_one_node);
726a989a 2259 gfc_add_modify (&block, count1, tmp);
6de9cd9a
DN
2260 }
2261 else
2262 {
8de1f441 2263 /* Increment count1. */
10c7a96f 2264 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
8de1f441 2265 count1, gfc_index_one_node);
726a989a 2266 gfc_add_modify (&body1, count1, tmp);
6de9cd9a
DN
2267
2268 /* Increment count3. */
2269 if (count3)
8de1f441
JJ
2270 {
2271 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
10c7a96f 2272 count3, gfc_index_one_node);
726a989a 2273 gfc_add_modify (&body1, count3, tmp);
8de1f441 2274 }
6de9cd9a
DN
2275
2276 /* Generate the copying loops. */
2277 gfc_trans_scalarizing_loops (&loop, &body1);
2278
2279 gfc_add_block_to_block (&block, &loop.pre);
2280 gfc_add_block_to_block (&block, &loop.post);
2281
2282 gfc_cleanup_loop (&loop);
2283 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
8de1f441 2284 as tree nodes in SS may not be valid in different scope. */
6de9cd9a 2285 }
6de9cd9a
DN
2286
2287 tmp = gfc_finish_block (&block);
2288 return tmp;
2289}
2290
2291
2292/* Calculate the size of temporary needed in the assignment inside forall.
2293 LSS and RSS are filled in this function. */
2294
2295static tree
2296compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
2297 stmtblock_t * pblock,
2298 gfc_ss **lss, gfc_ss **rss)
2299{
2300 gfc_loopinfo loop;
2301 tree size;
2302 int i;
ca86ddcc 2303 int save_flag;
6de9cd9a
DN
2304 tree tmp;
2305
2306 *lss = gfc_walk_expr (expr1);
2307 *rss = NULL;
2308
7ab92584 2309 size = gfc_index_one_node;
6de9cd9a
DN
2310 if (*lss != gfc_ss_terminator)
2311 {
2312 gfc_init_loopinfo (&loop);
2313
2314 /* Walk the RHS of the expression. */
2315 *rss = gfc_walk_expr (expr2);
2316 if (*rss == gfc_ss_terminator)
2317 {
2318 /* The rhs is scalar. Add a ss for the expression. */
2319 *rss = gfc_get_ss ();
2320 (*rss)->next = gfc_ss_terminator;
2321 (*rss)->type = GFC_SS_SCALAR;
2322 (*rss)->expr = expr2;
2323 }
2324
2325 /* Associate the SS with the loop. */
2326 gfc_add_ss_to_loop (&loop, *lss);
2327 /* We don't actually need to add the rhs at this point, but it might
2328 make guessing the loop bounds a bit easier. */
2329 gfc_add_ss_to_loop (&loop, *rss);
2330
2331 /* We only want the shape of the expression, not rest of the junk
2332 generated by the scalarizer. */
2333 loop.array_parameter = 1;
2334
2335 /* Calculate the bounds of the scalarization. */
d3d3011f
FXC
2336 save_flag = gfc_option.rtcheck;
2337 gfc_option.rtcheck &= !GFC_RTCHECK_BOUNDS;
6de9cd9a 2338 gfc_conv_ss_startstride (&loop);
d3d3011f 2339 gfc_option.rtcheck = save_flag;
bdfd2ff0 2340 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
2341
2342 /* Figure out how many elements we need. */
2343 for (i = 0; i < loop.dimen; i++)
2344 {
10c7a96f
SB
2345 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2346 gfc_index_one_node, loop.from[i]);
2347 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2348 tmp, loop.to[i]);
2349 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
6de9cd9a
DN
2350 }
2351 gfc_add_block_to_block (pblock, &loop.pre);
2352 size = gfc_evaluate_now (size, pblock);
2353 gfc_add_block_to_block (pblock, &loop.post);
2354
2355 /* TODO: write a function that cleans up a loopinfo without freeing
2356 the SS chains. Currently a NOP. */
2357 }
2358
2359 return size;
2360}
2361
2362
2ad62c9b
RS
2363/* Calculate the overall iterator number of the nested forall construct.
2364 This routine actually calculates the number of times the body of the
2365 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
2366 that by the expression INNER_SIZE. The BLOCK argument specifies the
2367 block in which to calculate the result, and the optional INNER_SIZE_BODY
2368 argument contains any statements that need to executed (inside the loop)
2369 to initialize or calculate INNER_SIZE. */
6de9cd9a
DN
2370
2371static tree
2372compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
8de1f441 2373 stmtblock_t *inner_size_body, stmtblock_t *block)
6de9cd9a 2374{
2ad62c9b 2375 forall_info *forall_tmp = nested_forall_info;
6de9cd9a
DN
2376 tree tmp, number;
2377 stmtblock_t body;
2378
2ad62c9b
RS
2379 /* We can eliminate the innermost unconditional loops with constant
2380 array bounds. */
3bf783b7
RS
2381 if (INTEGER_CST_P (inner_size))
2382 {
2ad62c9b
RS
2383 while (forall_tmp
2384 && !forall_tmp->mask
2385 && INTEGER_CST_P (forall_tmp->size))
3bf783b7 2386 {
2ad62c9b
RS
2387 inner_size = fold_build2 (MULT_EXPR, gfc_array_index_type,
2388 inner_size, forall_tmp->size);
2389 forall_tmp = forall_tmp->prev_nest;
3bf783b7 2390 }
2ad62c9b
RS
2391
2392 /* If there are no loops left, we have our constant result. */
2393 if (!forall_tmp)
2394 return inner_size;
3bf783b7 2395 }
2ad62c9b
RS
2396
2397 /* Otherwise, create a temporary variable to compute the result. */
6de9cd9a 2398 number = gfc_create_var (gfc_array_index_type, "num");
726a989a 2399 gfc_add_modify (block, number, gfc_index_zero_node);
6de9cd9a
DN
2400
2401 gfc_start_block (&body);
8de1f441
JJ
2402 if (inner_size_body)
2403 gfc_add_block_to_block (&body, inner_size_body);
2ad62c9b 2404 if (forall_tmp)
44855d8c
TS
2405 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2406 number, inner_size);
6de9cd9a
DN
2407 else
2408 tmp = inner_size;
726a989a 2409 gfc_add_modify (&body, number, tmp);
6de9cd9a
DN
2410 tmp = gfc_finish_block (&body);
2411
2412 /* Generate loops. */
2ad62c9b
RS
2413 if (forall_tmp != NULL)
2414 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
6de9cd9a
DN
2415
2416 gfc_add_expr_to_block (block, tmp);
2417
2418 return number;
2419}
2420
2421
8de1f441
JJ
2422/* Allocate temporary for forall construct. SIZE is the size of temporary
2423 needed. PTEMP1 is returned for space free. */
6de9cd9a
DN
2424
2425static tree
8de1f441
JJ
2426allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
2427 tree * ptemp1)
6de9cd9a 2428{
bfcabc6c 2429 tree bytesize;
6de9cd9a 2430 tree unit;
6de9cd9a 2431 tree tmp;
6de9cd9a 2432
7c57b2f1 2433 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
bfcabc6c
RS
2434 if (!integer_onep (unit))
2435 bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size, unit);
2436 else
2437 bytesize = size;
6de9cd9a
DN
2438
2439 *ptemp1 = NULL;
bfcabc6c 2440 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
6de9cd9a
DN
2441
2442 if (*ptemp1)
bfcabc6c 2443 tmp = build_fold_indirect_ref (tmp);
6de9cd9a
DN
2444 return tmp;
2445}
2446
2447
8de1f441
JJ
2448/* Allocate temporary for forall construct according to the information in
2449 nested_forall_info. INNER_SIZE is the size of temporary needed in the
2450 assignment inside forall. PTEMP1 is returned for space free. */
2451
2452static tree
2453allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
2454 tree inner_size, stmtblock_t * inner_size_body,
2455 stmtblock_t * block, tree * ptemp1)
2456{
2457 tree size;
2458
2459 /* Calculate the total size of temporary needed in forall construct. */
2460 size = compute_overall_iter_number (nested_forall_info, inner_size,
2461 inner_size_body, block);
2462
2463 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
2464}
2465
2466
2467/* Handle assignments inside forall which need temporary.
2468
2469 forall (i=start:end:stride; maskexpr)
2470 e<i> = f<i>
2471 end forall
2472 (where e,f<i> are arbitrary expressions possibly involving i
2473 and there is a dependency between e<i> and f<i>)
2474 Translates to:
2475 masktmp(:) = maskexpr(:)
2476
2477 maskindex = 0;
2478 count1 = 0;
2479 num = 0;
2480 for (i = start; i <= end; i += stride)
2481 num += SIZE (f<i>)
2482 count1 = 0;
2483 ALLOCATE (tmp(num))
2484 for (i = start; i <= end; i += stride)
2485 {
2486 if (masktmp[maskindex++])
2487 tmp[count1++] = f<i>
2488 }
2489 maskindex = 0;
2490 count1 = 0;
2491 for (i = start; i <= end; i += stride)
2492 {
2493 if (masktmp[maskindex++])
2494 e<i> = tmp[count1++]
2495 }
2496 DEALLOCATE (tmp)
2497 */
6de9cd9a 2498static void
011daa76
RS
2499gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2500 tree wheremask, bool invert,
6de9cd9a
DN
2501 forall_info * nested_forall_info,
2502 stmtblock_t * block)
2503{
2504 tree type;
2505 tree inner_size;
2506 gfc_ss *lss, *rss;
8de1f441 2507 tree count, count1;
6de9cd9a
DN
2508 tree tmp, tmp1;
2509 tree ptemp1;
8de1f441 2510 stmtblock_t inner_size_body;
6de9cd9a 2511
8de1f441
JJ
2512 /* Create vars. count1 is the current iterator number of the nested
2513 forall. */
6de9cd9a 2514 count1 = gfc_create_var (gfc_array_index_type, "count1");
6de9cd9a
DN
2515
2516 /* Count is the wheremask index. */
2517 if (wheremask)
2518 {
2519 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 2520 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
2521 }
2522 else
2523 count = NULL;
2524
2525 /* Initialize count1. */
726a989a 2526 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a
DN
2527
2528 /* Calculate the size of temporary needed in the assignment. Return loop, lss
2529 and rss which are used in function generate_loop_for_rhs_to_temp(). */
8de1f441
JJ
2530 gfc_init_block (&inner_size_body);
2531 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
2532 &lss, &rss);
6de9cd9a
DN
2533
2534 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
640670c7
PT
2535 if (expr1->ts.type == BT_CHARACTER && expr1->ts.cl->length)
2536 {
2537 if (!expr1->ts.cl->backend_decl)
2538 {
2539 gfc_se tse;
2540 gfc_init_se (&tse, NULL);
2541 gfc_conv_expr (&tse, expr1->ts.cl->length);
2542 expr1->ts.cl->backend_decl = tse.expr;
2543 }
2544 type = gfc_get_character_type_len (gfc_default_character_kind,
2545 expr1->ts.cl->backend_decl);
2546 }
2547 else
2548 type = gfc_typenode_for_spec (&expr1->ts);
6de9cd9a
DN
2549
2550 /* Allocate temporary for nested forall construct according to the
f7b529fa 2551 information in nested_forall_info and inner_size. */
8de1f441
JJ
2552 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
2553 &inner_size_body, block, &ptemp1);
6de9cd9a 2554
6de9cd9a 2555 /* Generate codes to copy rhs to the temporary . */
8de1f441 2556 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
011daa76 2557 wheremask, invert);
6de9cd9a 2558
1f2959f0 2559 /* Generate body and loops according to the information in
6de9cd9a 2560 nested_forall_info. */
bfcabc6c 2561 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2562 gfc_add_expr_to_block (block, tmp);
2563
2564 /* Reset count1. */
726a989a 2565 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a 2566
6de9cd9a
DN
2567 /* Reset count. */
2568 if (wheremask)
726a989a 2569 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
2570
2571 /* Generate codes to copy the temporary to lhs. */
011daa76
RS
2572 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
2573 wheremask, invert);
6de9cd9a 2574
1f2959f0 2575 /* Generate body and loops according to the information in
6de9cd9a 2576 nested_forall_info. */
bfcabc6c 2577 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2578 gfc_add_expr_to_block (block, tmp);
2579
2580 if (ptemp1)
2581 {
2582 /* Free the temporary. */
1529b8d9 2583 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
2584 gfc_add_expr_to_block (block, tmp);
2585 }
2586}
2587
2588
2589/* Translate pointer assignment inside FORALL which need temporary. */
2590
2591static void
2592gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2593 forall_info * nested_forall_info,
2594 stmtblock_t * block)
2595{
2596 tree type;
2597 tree inner_size;
2598 gfc_ss *lss, *rss;
2599 gfc_se lse;
2600 gfc_se rse;
2601 gfc_ss_info *info;
2602 gfc_loopinfo loop;
2603 tree desc;
2604 tree parm;
2605 tree parmtype;
2606 stmtblock_t body;
2607 tree count;
2608 tree tmp, tmp1, ptemp1;
6de9cd9a
DN
2609
2610 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 2611 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
2612
2613 inner_size = integer_one_node;
2614 lss = gfc_walk_expr (expr1);
2615 rss = gfc_walk_expr (expr2);
2616 if (lss == gfc_ss_terminator)
2617 {
2618 type = gfc_typenode_for_spec (&expr1->ts);
2619 type = build_pointer_type (type);
2620
2621 /* Allocate temporary for nested forall construct according to the
2622 information in nested_forall_info and inner_size. */
8de1f441
JJ
2623 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
2624 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
2625 gfc_start_block (&body);
2626 gfc_init_se (&lse, NULL);
1d6b7f39 2627 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2628 gfc_init_se (&rse, NULL);
2629 rse.want_pointer = 1;
2630 gfc_conv_expr (&rse, expr2);
2631 gfc_add_block_to_block (&body, &rse.pre);
726a989a 2632 gfc_add_modify (&body, lse.expr,
cc2804f1 2633 fold_convert (TREE_TYPE (lse.expr), rse.expr));
6de9cd9a
DN
2634 gfc_add_block_to_block (&body, &rse.post);
2635
2636 /* Increment count. */
10c7a96f
SB
2637 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2638 count, gfc_index_one_node);
726a989a 2639 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2640
2641 tmp = gfc_finish_block (&body);
2642
1f2959f0 2643 /* Generate body and loops according to the information in
6de9cd9a 2644 nested_forall_info. */
bfcabc6c 2645 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2646 gfc_add_expr_to_block (block, tmp);
2647
2648 /* Reset count. */
726a989a 2649 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 2650
6de9cd9a
DN
2651 gfc_start_block (&body);
2652 gfc_init_se (&lse, NULL);
2653 gfc_init_se (&rse, NULL);
1d6b7f39 2654 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2655 lse.want_pointer = 1;
2656 gfc_conv_expr (&lse, expr1);
2657 gfc_add_block_to_block (&body, &lse.pre);
726a989a 2658 gfc_add_modify (&body, lse.expr, rse.expr);
6de9cd9a
DN
2659 gfc_add_block_to_block (&body, &lse.post);
2660 /* Increment count. */
10c7a96f
SB
2661 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2662 count, gfc_index_one_node);
726a989a 2663 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2664 tmp = gfc_finish_block (&body);
2665
1f2959f0 2666 /* Generate body and loops according to the information in
6de9cd9a 2667 nested_forall_info. */
bfcabc6c 2668 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2669 gfc_add_expr_to_block (block, tmp);
2670 }
2671 else
2672 {
2673 gfc_init_loopinfo (&loop);
2674
2675 /* Associate the SS with the loop. */
2676 gfc_add_ss_to_loop (&loop, rss);
2677
2678 /* Setup the scalarizing loops and bounds. */
2679 gfc_conv_ss_startstride (&loop);
2680
bdfd2ff0 2681 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
2682
2683 info = &rss->data.info;
2684 desc = info->descriptor;
2685
2686 /* Make a new descriptor. */
2687 parmtype = gfc_get_element_type (TREE_TYPE (desc));
2688 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
fad0afd7
JJ
2689 loop.from, loop.to, 1,
2690 GFC_ARRAY_UNKNOWN);
6de9cd9a
DN
2691
2692 /* Allocate temporary for nested forall construct. */
2693 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
8de1f441 2694 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
2695 gfc_start_block (&body);
2696 gfc_init_se (&lse, NULL);
1d6b7f39 2697 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2698 lse.direct_byref = 1;
2699 rss = gfc_walk_expr (expr2);
2700 gfc_conv_expr_descriptor (&lse, expr2, rss);
2701
2702 gfc_add_block_to_block (&body, &lse.pre);
2703 gfc_add_block_to_block (&body, &lse.post);
2704
2705 /* Increment count. */
10c7a96f
SB
2706 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2707 count, gfc_index_one_node);
726a989a 2708 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2709
2710 tmp = gfc_finish_block (&body);
2711
1f2959f0 2712 /* Generate body and loops according to the information in
6de9cd9a 2713 nested_forall_info. */
bfcabc6c 2714 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2715 gfc_add_expr_to_block (block, tmp);
2716
2717 /* Reset count. */
726a989a 2718 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 2719
1d6b7f39 2720 parm = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2721 lss = gfc_walk_expr (expr1);
2722 gfc_init_se (&lse, NULL);
2723 gfc_conv_expr_descriptor (&lse, expr1, lss);
726a989a 2724 gfc_add_modify (&lse.pre, lse.expr, parm);
6de9cd9a
DN
2725 gfc_start_block (&body);
2726 gfc_add_block_to_block (&body, &lse.pre);
2727 gfc_add_block_to_block (&body, &lse.post);
2728
2729 /* Increment count. */
10c7a96f
SB
2730 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2731 count, gfc_index_one_node);
726a989a 2732 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2733
2734 tmp = gfc_finish_block (&body);
2735
bfcabc6c 2736 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2737 gfc_add_expr_to_block (block, tmp);
2738 }
2739 /* Free the temporary. */
2740 if (ptemp1)
2741 {
1529b8d9 2742 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
2743 gfc_add_expr_to_block (block, tmp);
2744 }
2745}
2746
2747
2748/* FORALL and WHERE statements are really nasty, especially when you nest
2749 them. All the rhs of a forall assignment must be evaluated before the
2750 actual assignments are performed. Presumably this also applies to all the
2751 assignments in an inner where statement. */
2752
2753/* Generate code for a FORALL statement. Any temporaries are allocated as a
2754 linear array, relying on the fact that we process in the same order in all
2755 loops.
2756
2757 forall (i=start:end:stride; maskexpr)
2758 e<i> = f<i>
2759 g<i> = h<i>
2760 end forall
e7dc5b4f 2761 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
6de9cd9a 2762 Translates to:
8de1f441 2763 count = ((end + 1 - start) / stride)
6de9cd9a
DN
2764 masktmp(:) = maskexpr(:)
2765
2766 maskindex = 0;
2767 for (i = start; i <= end; i += stride)
2768 {
2769 if (masktmp[maskindex++])
2770 e<i> = f<i>
2771 }
2772 maskindex = 0;
2773 for (i = start; i <= end; i += stride)
2774 {
2775 if (masktmp[maskindex++])
cafa34aa 2776 g<i> = h<i>
6de9cd9a
DN
2777 }
2778
2779 Note that this code only works when there are no dependencies.
2780 Forall loop with array assignments and data dependencies are a real pain,
2781 because the size of the temporary cannot always be determined before the
1f2959f0 2782 loop is executed. This problem is compounded by the presence of nested
6de9cd9a
DN
2783 FORALL constructs.
2784 */
2785
2786static tree
2787gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
2788{
640670c7
PT
2789 stmtblock_t pre;
2790 stmtblock_t post;
6de9cd9a
DN
2791 stmtblock_t block;
2792 stmtblock_t body;
2793 tree *var;
2794 tree *start;
2795 tree *end;
2796 tree *step;
2797 gfc_expr **varexpr;
2798 tree tmp;
2799 tree assign;
2800 tree size;
6de9cd9a
DN
2801 tree maskindex;
2802 tree mask;
2803 tree pmask;
2804 int n;
2805 int nvar;
2806 int need_temp;
2807 gfc_forall_iterator *fa;
2808 gfc_se se;
2809 gfc_code *c;
7b5b57b7 2810 gfc_saved_var *saved_vars;
bfcabc6c
RS
2811 iter_info *this_forall;
2812 forall_info *info;
e35a0e64
RS
2813 bool need_mask;
2814
2815 /* Do nothing if the mask is false. */
2816 if (code->expr
2817 && code->expr->expr_type == EXPR_CONSTANT
2818 && !code->expr->value.logical)
2819 return build_empty_stmt ();
6de9cd9a
DN
2820
2821 n = 0;
2822 /* Count the FORALL index number. */
2823 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2824 n++;
2825 nvar = n;
2826
2827 /* Allocate the space for var, start, end, step, varexpr. */
2828 var = (tree *) gfc_getmem (nvar * sizeof (tree));
2829 start = (tree *) gfc_getmem (nvar * sizeof (tree));
2830 end = (tree *) gfc_getmem (nvar * sizeof (tree));
2831 step = (tree *) gfc_getmem (nvar * sizeof (tree));
2832 varexpr = (gfc_expr **) gfc_getmem (nvar * sizeof (gfc_expr *));
7b5b57b7 2833 saved_vars = (gfc_saved_var *) gfc_getmem (nvar * sizeof (gfc_saved_var));
6de9cd9a
DN
2834
2835 /* Allocate the space for info. */
2836 info = (forall_info *) gfc_getmem (sizeof (forall_info));
bfcabc6c 2837
640670c7
PT
2838 gfc_start_block (&pre);
2839 gfc_init_block (&post);
2840 gfc_init_block (&block);
bfcabc6c 2841
6de9cd9a
DN
2842 n = 0;
2843 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2844 {
2845 gfc_symbol *sym = fa->var->symtree->n.sym;
2846
bfcabc6c 2847 /* Allocate space for this_forall. */
6de9cd9a
DN
2848 this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
2849
6de9cd9a
DN
2850 /* Create a temporary variable for the FORALL index. */
2851 tmp = gfc_typenode_for_spec (&sym->ts);
2852 var[n] = gfc_create_var (tmp, sym->name);
7b5b57b7
PB
2853 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
2854
6de9cd9a
DN
2855 /* Record it in this_forall. */
2856 this_forall->var = var[n];
2857
2858 /* Replace the index symbol's backend_decl with the temporary decl. */
2859 sym->backend_decl = var[n];
2860
2861 /* Work out the start, end and stride for the loop. */
2862 gfc_init_se (&se, NULL);
2863 gfc_conv_expr_val (&se, fa->start);
2864 /* Record it in this_forall. */
2865 this_forall->start = se.expr;
2866 gfc_add_block_to_block (&block, &se.pre);
2867 start[n] = se.expr;
2868
2869 gfc_init_se (&se, NULL);
2870 gfc_conv_expr_val (&se, fa->end);
2871 /* Record it in this_forall. */
2872 this_forall->end = se.expr;
2873 gfc_make_safe_expr (&se);
2874 gfc_add_block_to_block (&block, &se.pre);
2875 end[n] = se.expr;
2876
2877 gfc_init_se (&se, NULL);
2878 gfc_conv_expr_val (&se, fa->stride);
2879 /* Record it in this_forall. */
2880 this_forall->step = se.expr;
2881 gfc_make_safe_expr (&se);
2882 gfc_add_block_to_block (&block, &se.pre);
2883 step[n] = se.expr;
2884
2885 /* Set the NEXT field of this_forall to NULL. */
2886 this_forall->next = NULL;
2887 /* Link this_forall to the info construct. */
bfcabc6c 2888 if (info->this_loop)
6de9cd9a 2889 {
bfcabc6c 2890 iter_info *iter_tmp = info->this_loop;
6de9cd9a
DN
2891 while (iter_tmp->next != NULL)
2892 iter_tmp = iter_tmp->next;
2893 iter_tmp->next = this_forall;
2894 }
bfcabc6c
RS
2895 else
2896 info->this_loop = this_forall;
6de9cd9a
DN
2897
2898 n++;
2899 }
2900 nvar = n;
2901
bfcabc6c 2902 /* Calculate the size needed for the current forall level. */
7ab92584 2903 size = gfc_index_one_node;
6de9cd9a
DN
2904 for (n = 0; n < nvar; n++)
2905 {
6de9cd9a 2906 /* size = (end + step - start) / step. */
10c7a96f
SB
2907 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (start[n]),
2908 step[n], start[n]);
2909 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (end[n]), end[n], tmp);
6de9cd9a 2910
10c7a96f 2911 tmp = fold_build2 (FLOOR_DIV_EXPR, TREE_TYPE (tmp), tmp, step[n]);
6de9cd9a
DN
2912 tmp = convert (gfc_array_index_type, tmp);
2913
10c7a96f 2914 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
6de9cd9a
DN
2915 }
2916
2917 /* Record the nvar and size of current forall level. */
2918 info->nvar = nvar;
2919 info->size = size;
2920
bfcabc6c 2921 if (code->expr)
e35a0e64
RS
2922 {
2923 /* If the mask is .true., consider the FORALL unconditional. */
2924 if (code->expr->expr_type == EXPR_CONSTANT
2925 && code->expr->value.logical)
2926 need_mask = false;
2927 else
2928 need_mask = true;
2929 }
2930 else
2931 need_mask = false;
2932
2933 /* First we need to allocate the mask. */
2934 if (need_mask)
bfcabc6c
RS
2935 {
2936 /* As the mask array can be very big, prefer compact boolean types. */
2937 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
2938 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
2939 size, NULL, &block, &pmask);
2940 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
2941
2942 /* Record them in the info structure. */
2943 info->maskindex = maskindex;
2944 info->mask = mask;
2945 }
6de9cd9a
DN
2946 else
2947 {
bfcabc6c
RS
2948 /* No mask was specified. */
2949 maskindex = NULL_TREE;
2950 mask = pmask = NULL_TREE;
2951 }
2952
2953 /* Link the current forall level to nested_forall_info. */
e8d366ec
RS
2954 info->prev_nest = nested_forall_info;
2955 nested_forall_info = info;
6de9cd9a
DN
2956
2957 /* Copy the mask into a temporary variable if required.
f7b529fa 2958 For now we assume a mask temporary is needed. */
e35a0e64 2959 if (need_mask)
6de9cd9a 2960 {
bfcabc6c
RS
2961 /* As the mask array can be very big, prefer compact boolean types. */
2962 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
6de9cd9a 2963
726a989a 2964 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
6de9cd9a
DN
2965
2966 /* Start of mask assignment loop body. */
2967 gfc_start_block (&body);
2968
2969 /* Evaluate the mask expression. */
2970 gfc_init_se (&se, NULL);
2971 gfc_conv_expr_val (&se, code->expr);
2972 gfc_add_block_to_block (&body, &se.pre);
2973
2974 /* Store the mask. */
bfcabc6c 2975 se.expr = convert (mask_type, se.expr);
6de9cd9a 2976
1d6b7f39 2977 tmp = gfc_build_array_ref (mask, maskindex, NULL);
726a989a 2978 gfc_add_modify (&body, tmp, se.expr);
6de9cd9a
DN
2979
2980 /* Advance to the next mask element. */
44855d8c
TS
2981 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2982 maskindex, gfc_index_one_node);
726a989a 2983 gfc_add_modify (&body, maskindex, tmp);
6de9cd9a
DN
2984
2985 /* Generate the loops. */
2986 tmp = gfc_finish_block (&body);
bfcabc6c 2987 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
6de9cd9a
DN
2988 gfc_add_expr_to_block (&block, tmp);
2989 }
6de9cd9a
DN
2990
2991 c = code->block->next;
2992
2993 /* TODO: loop merging in FORALL statements. */
2994 /* Now that we've got a copy of the mask, generate the assignment loops. */
2995 while (c)
2996 {
2997 switch (c->op)
2998 {
2999 case EXEC_ASSIGN:
640670c7
PT
3000 /* A scalar or array assignment. DO the simple check for
3001 lhs to rhs dependencies. These make a temporary for the
3002 rhs and form a second forall block to copy to variable. */
3003 need_temp = check_forall_dependencies(c, &pre, &post);
3004
69de3b83 3005 /* Temporaries due to array assignment data dependencies introduce
6de9cd9a
DN
3006 no end of problems. */
3007 if (need_temp)
011daa76 3008 gfc_trans_assign_need_temp (c->expr, c->expr2, NULL, false,
6de9cd9a
DN
3009 nested_forall_info, &block);
3010 else
3011 {
3012 /* Use the normal assignment copying routines. */
6b591ec0 3013 assign = gfc_trans_assignment (c->expr, c->expr2, false);
6de9cd9a 3014
6de9cd9a 3015 /* Generate body and loops. */
bfcabc6c
RS
3016 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3017 assign, 1);
6de9cd9a
DN
3018 gfc_add_expr_to_block (&block, tmp);
3019 }
3020
640670c7
PT
3021 /* Cleanup any temporary symtrees that have been made to deal
3022 with dependencies. */
3023 if (new_symtree)
3024 cleanup_forall_symtrees (c);
3025
6de9cd9a
DN
3026 break;
3027
3028 case EXEC_WHERE:
6de9cd9a 3029 /* Translate WHERE or WHERE construct nested in FORALL. */
011daa76 3030 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3891cee2 3031 break;
6de9cd9a
DN
3032
3033 /* Pointer assignment inside FORALL. */
3034 case EXEC_POINTER_ASSIGN:
3ded6210 3035 need_temp = gfc_check_dependency (c->expr, c->expr2, 0);
6de9cd9a
DN
3036 if (need_temp)
3037 gfc_trans_pointer_assign_need_temp (c->expr, c->expr2,
3038 nested_forall_info, &block);
3039 else
3040 {
3041 /* Use the normal assignment copying routines. */
3042 assign = gfc_trans_pointer_assignment (c->expr, c->expr2);
3043
6de9cd9a 3044 /* Generate body and loops. */
bfcabc6c
RS
3045 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3046 assign, 1);
6de9cd9a
DN
3047 gfc_add_expr_to_block (&block, tmp);
3048 }
3049 break;
3050
3051 case EXEC_FORALL:
3052 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3053 gfc_add_expr_to_block (&block, tmp);
3054 break;
3055
48474141
PT
3056 /* Explicit subroutine calls are prevented by the frontend but interface
3057 assignments can legitimately produce them. */
476220e7 3058 case EXEC_ASSIGN_CALL:
eb74e79b 3059 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
bfcabc6c 3060 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
48474141
PT
3061 gfc_add_expr_to_block (&block, tmp);
3062 break;
3063
6de9cd9a 3064 default:
6e45f57b 3065 gcc_unreachable ();
6de9cd9a
DN
3066 }
3067
3068 c = c->next;
3069 }
3070
7b5b57b7
PB
3071 /* Restore the original index variables. */
3072 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3073 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
6de9cd9a
DN
3074
3075 /* Free the space for var, start, end, step, varexpr. */
3076 gfc_free (var);
3077 gfc_free (start);
3078 gfc_free (end);
3079 gfc_free (step);
3080 gfc_free (varexpr);
7b5b57b7 3081 gfc_free (saved_vars);
6de9cd9a 3082
e8d366ec
RS
3083 /* Free the space for this forall_info. */
3084 gfc_free (info);
3085
6de9cd9a
DN
3086 if (pmask)
3087 {
3088 /* Free the temporary for the mask. */
1529b8d9 3089 tmp = gfc_call_free (pmask);
6de9cd9a
DN
3090 gfc_add_expr_to_block (&block, tmp);
3091 }
3092 if (maskindex)
3093 pushdecl (maskindex);
3094
640670c7
PT
3095 gfc_add_block_to_block (&pre, &block);
3096 gfc_add_block_to_block (&pre, &post);
3097
3098 return gfc_finish_block (&pre);
6de9cd9a
DN
3099}
3100
3101
3102/* Translate the FORALL statement or construct. */
3103
3104tree gfc_trans_forall (gfc_code * code)
3105{
3106 return gfc_trans_forall_1 (code, NULL);
3107}
3108
3109
3110/* Evaluate the WHERE mask expression, copy its value to a temporary.
3111 If the WHERE construct is nested in FORALL, compute the overall temporary
3112 needed by the WHERE mask expression multiplied by the iterator number of
3113 the nested forall.
3114 ME is the WHERE mask expression.
011daa76
RS
3115 MASK is the current execution mask upon input, whose sense may or may
3116 not be inverted as specified by the INVERT argument.
3891cee2
RS
3117 CMASK is the updated execution mask on output, or NULL if not required.
3118 PMASK is the pending execution mask on output, or NULL if not required.
3119 BLOCK is the block in which to place the condition evaluation loops. */
6de9cd9a 3120
3891cee2 3121static void
6de9cd9a 3122gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
011daa76 3123 tree mask, bool invert, tree cmask, tree pmask,
3891cee2 3124 tree mask_type, stmtblock_t * block)
6de9cd9a
DN
3125{
3126 tree tmp, tmp1;
3127 gfc_ss *lss, *rss;
3128 gfc_loopinfo loop;
3891cee2
RS
3129 stmtblock_t body, body1;
3130 tree count, cond, mtmp;
6de9cd9a 3131 gfc_se lse, rse;
6de9cd9a
DN
3132
3133 gfc_init_loopinfo (&loop);
3134
3891cee2
RS
3135 lss = gfc_walk_expr (me);
3136 rss = gfc_walk_expr (me);
6de9cd9a
DN
3137
3138 /* Variable to index the temporary. */
3139 count = gfc_create_var (gfc_array_index_type, "count");
1f2959f0 3140 /* Initialize count. */
726a989a 3141 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
3142
3143 gfc_start_block (&body);
3144
3145 gfc_init_se (&rse, NULL);
3146 gfc_init_se (&lse, NULL);
3147
3148 if (lss == gfc_ss_terminator)
3149 {
3150 gfc_init_block (&body1);
3151 }
3152 else
3153 {
1f2959f0 3154 /* Initialize the loop. */
6de9cd9a
DN
3155 gfc_init_loopinfo (&loop);
3156
3157 /* We may need LSS to determine the shape of the expression. */
3158 gfc_add_ss_to_loop (&loop, lss);
3159 gfc_add_ss_to_loop (&loop, rss);
3160
3161 gfc_conv_ss_startstride (&loop);
bdfd2ff0 3162 gfc_conv_loop_setup (&loop, &me->where);
6de9cd9a
DN
3163
3164 gfc_mark_ss_chain_used (rss, 1);
3165 /* Start the loop body. */
3166 gfc_start_scalarized_body (&loop, &body1);
3167
3168 /* Translate the expression. */
3169 gfc_copy_loopinfo_to_se (&rse, &loop);
3170 rse.ss = rss;
3171 gfc_conv_expr (&rse, me);
3172 }
6de9cd9a 3173
b82feea5 3174 /* Variable to evaluate mask condition. */
3891cee2
RS
3175 cond = gfc_create_var (mask_type, "cond");
3176 if (mask && (cmask || pmask))
3177 mtmp = gfc_create_var (mask_type, "mask");
3178 else mtmp = NULL_TREE;
3179
3180 gfc_add_block_to_block (&body1, &lse.pre);
3181 gfc_add_block_to_block (&body1, &rse.pre);
6de9cd9a 3182
726a989a 3183 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
3891cee2
RS
3184
3185 if (mask && (cmask || pmask))
42e73749 3186 {
1d6b7f39 3187 tmp = gfc_build_array_ref (mask, count, NULL);
011daa76
RS
3188 if (invert)
3189 tmp = fold_build1 (TRUTH_NOT_EXPR, mask_type, tmp);
726a989a 3190 gfc_add_modify (&body1, mtmp, tmp);
42e73749 3191 }
6de9cd9a 3192
3891cee2
RS
3193 if (cmask)
3194 {
1d6b7f39 3195 tmp1 = gfc_build_array_ref (cmask, count, NULL);
3891cee2
RS
3196 tmp = cond;
3197 if (mask)
44855d8c 3198 tmp = fold_build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp);
726a989a 3199 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
3200 }
3201
3202 if (pmask)
3203 {
1d6b7f39 3204 tmp1 = gfc_build_array_ref (pmask, count, NULL);
44855d8c 3205 tmp = fold_build1 (TRUTH_NOT_EXPR, mask_type, cond);
3891cee2 3206 if (mask)
44855d8c 3207 tmp = fold_build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp);
726a989a 3208 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
3209 }
3210
3211 gfc_add_block_to_block (&body1, &lse.post);
3212 gfc_add_block_to_block (&body1, &rse.post);
3213
3214 if (lss == gfc_ss_terminator)
6de9cd9a
DN
3215 {
3216 gfc_add_block_to_block (&body, &body1);
3217 }
3218 else
3219 {
3220 /* Increment count. */
10c7a96f
SB
3221 tmp1 = fold_build2 (PLUS_EXPR, gfc_array_index_type, count,
3222 gfc_index_one_node);
726a989a 3223 gfc_add_modify (&body1, count, tmp1);
6de9cd9a
DN
3224
3225 /* Generate the copying loops. */
3226 gfc_trans_scalarizing_loops (&loop, &body1);
3227
3228 gfc_add_block_to_block (&body, &loop.pre);
3229 gfc_add_block_to_block (&body, &loop.post);
3230
3231 gfc_cleanup_loop (&loop);
3232 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3233 as tree nodes in SS may not be valid in different scope. */
3234 }
3235
3236 tmp1 = gfc_finish_block (&body);
3237 /* If the WHERE construct is inside FORALL, fill the full temporary. */
3238 if (nested_forall_info != NULL)
bfcabc6c 3239 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
6de9cd9a
DN
3240
3241 gfc_add_expr_to_block (block, tmp1);
6de9cd9a
DN
3242}
3243
3244
3245/* Translate an assignment statement in a WHERE statement or construct
3246 statement. The MASK expression is used to control which elements
011daa76
RS
3247 of EXPR1 shall be assigned. The sense of MASK is specified by
3248 INVERT. */
6de9cd9a
DN
3249
3250static tree
011daa76
RS
3251gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
3252 tree mask, bool invert,
a00b8d1a 3253 tree count1, tree count2,
eb74e79b 3254 gfc_code *cnext)
6de9cd9a
DN
3255{
3256 gfc_se lse;
3257 gfc_se rse;
3258 gfc_ss *lss;
3259 gfc_ss *lss_section;
3260 gfc_ss *rss;
3261
3262 gfc_loopinfo loop;
3263 tree tmp;
3264 stmtblock_t block;
3265 stmtblock_t body;
3c90c9ae 3266 tree index, maskexpr;
6de9cd9a 3267
eb74e79b
PT
3268 /* A defined assignment. */
3269 if (cnext && cnext->resolved_sym)
3270 return gfc_trans_call (cnext, true, mask, count1, invert);
3271
6de9cd9a
DN
3272#if 0
3273 /* TODO: handle this special case.
3274 Special case a single function returning an array. */
3275 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
3276 {
3277 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
3278 if (tmp)
3279 return tmp;
3280 }
3281#endif
3282
3283 /* Assignment of the form lhs = rhs. */
3284 gfc_start_block (&block);
3285
3286 gfc_init_se (&lse, NULL);
3287 gfc_init_se (&rse, NULL);
3288
3289 /* Walk the lhs. */
3290 lss = gfc_walk_expr (expr1);
3291 rss = NULL;
3292
3293 /* In each where-assign-stmt, the mask-expr and the variable being
3294 defined shall be arrays of the same shape. */
6e45f57b 3295 gcc_assert (lss != gfc_ss_terminator);
6de9cd9a
DN
3296
3297 /* The assignment needs scalarization. */
3298 lss_section = lss;
3299
3300 /* Find a non-scalar SS from the lhs. */
3301 while (lss_section != gfc_ss_terminator
3302 && lss_section->type != GFC_SS_SECTION)
3303 lss_section = lss_section->next;
3304
6e45f57b 3305 gcc_assert (lss_section != gfc_ss_terminator);
6de9cd9a
DN
3306
3307 /* Initialize the scalarizer. */
3308 gfc_init_loopinfo (&loop);
3309
3310 /* Walk the rhs. */
3311 rss = gfc_walk_expr (expr2);
3312 if (rss == gfc_ss_terminator)
3313 {
3314 /* The rhs is scalar. Add a ss for the expression. */
3315 rss = gfc_get_ss ();
ae772c2d 3316 rss->where = 1;
6de9cd9a
DN
3317 rss->next = gfc_ss_terminator;
3318 rss->type = GFC_SS_SCALAR;
3319 rss->expr = expr2;
3320 }
3321
3322 /* Associate the SS with the loop. */
3323 gfc_add_ss_to_loop (&loop, lss);
3324 gfc_add_ss_to_loop (&loop, rss);
3325
3326 /* Calculate the bounds of the scalarization. */
3327 gfc_conv_ss_startstride (&loop);
3328
3329 /* Resolve any data dependencies in the statement. */
3330 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
3331
3332 /* Setup the scalarizing loops. */
bdfd2ff0 3333 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
3334
3335 /* Setup the gfc_se structures. */
3336 gfc_copy_loopinfo_to_se (&lse, &loop);
3337 gfc_copy_loopinfo_to_se (&rse, &loop);
3338
3339 rse.ss = rss;
3340 gfc_mark_ss_chain_used (rss, 1);
3341 if (loop.temp_ss == NULL)
3342 {
3343 lse.ss = lss;
3344 gfc_mark_ss_chain_used (lss, 1);
3345 }
3346 else
3347 {
3348 lse.ss = loop.temp_ss;
3349 gfc_mark_ss_chain_used (lss, 3);
3350 gfc_mark_ss_chain_used (loop.temp_ss, 3);
3351 }
3352
3353 /* Start the scalarized loop body. */
3354 gfc_start_scalarized_body (&loop, &body);
3355
3356 /* Translate the expression. */
3357 gfc_conv_expr (&rse, expr2);
3358 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
3359 {
3360 gfc_conv_tmp_array_ref (&lse);
3361 gfc_advance_se_ss_chain (&lse);
3362 }
3363 else
3364 gfc_conv_expr (&lse, expr1);
3365
3c90c9ae 3366 /* Form the mask expression according to the mask. */
6de9cd9a 3367 index = count1;
1d6b7f39 3368 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76
RS
3369 if (invert)
3370 maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr), maskexpr);
6de9cd9a 3371
6de9cd9a 3372 /* Use the scalar assignment as is. */
eb74e79b
PT
3373 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
3374 loop.temp_ss != NULL, false);
a00b8d1a 3375
923ab88c 3376 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
6de9cd9a
DN
3377
3378 gfc_add_expr_to_block (&body, tmp);
3379
3380 if (lss == gfc_ss_terminator)
3381 {
3382 /* Increment count1. */
10c7a96f
SB
3383 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3384 count1, gfc_index_one_node);
726a989a 3385 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
3386
3387 /* Use the scalar assignment as is. */
3388 gfc_add_block_to_block (&block, &body);
3389 }
3390 else
3391 {
6e45f57b
PB
3392 gcc_assert (lse.ss == gfc_ss_terminator
3393 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
3394
3395 if (loop.temp_ss != NULL)
3396 {
3397 /* Increment count1 before finish the main body of a scalarized
3398 expression. */
10c7a96f
SB
3399 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3400 count1, gfc_index_one_node);
726a989a 3401 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
3402 gfc_trans_scalarized_loop_boundary (&loop, &body);
3403
3404 /* We need to copy the temporary to the actual lhs. */
3405 gfc_init_se (&lse, NULL);
3406 gfc_init_se (&rse, NULL);
3407 gfc_copy_loopinfo_to_se (&lse, &loop);
3408 gfc_copy_loopinfo_to_se (&rse, &loop);
3409
3410 rse.ss = loop.temp_ss;
3411 lse.ss = lss;
3412
3413 gfc_conv_tmp_array_ref (&rse);
3414 gfc_advance_se_ss_chain (&rse);
3415 gfc_conv_expr (&lse, expr1);
3416
6e45f57b
PB
3417 gcc_assert (lse.ss == gfc_ss_terminator
3418 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
3419
3420 /* Form the mask expression according to the mask tree list. */
3421 index = count2;
1d6b7f39 3422 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76
RS
3423 if (invert)
3424 maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr),
3425 maskexpr);
6de9cd9a 3426
6de9cd9a 3427 /* Use the scalar assignment as is. */
5046aff5 3428 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false);
923ab88c 3429 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
6de9cd9a 3430 gfc_add_expr_to_block (&body, tmp);
7ab92584 3431
6de9cd9a 3432 /* Increment count2. */
10c7a96f
SB
3433 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3434 count2, gfc_index_one_node);
726a989a 3435 gfc_add_modify (&body, count2, tmp);
6de9cd9a
DN
3436 }
3437 else
3438 {
3439 /* Increment count1. */
10c7a96f
SB
3440 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3441 count1, gfc_index_one_node);
726a989a 3442 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
3443 }
3444
3445 /* Generate the copying loops. */
3446 gfc_trans_scalarizing_loops (&loop, &body);
3447
3448 /* Wrap the whole thing up. */
3449 gfc_add_block_to_block (&block, &loop.pre);
3450 gfc_add_block_to_block (&block, &loop.post);
3451 gfc_cleanup_loop (&loop);
3452 }
3453
3454 return gfc_finish_block (&block);
3455}
3456
3457
3458/* Translate the WHERE construct or statement.
aa9c57ec 3459 This function can be called iteratively to translate the nested WHERE
6de9cd9a 3460 construct or statement.
3891cee2 3461 MASK is the control mask. */
6de9cd9a
DN
3462
3463static void
011daa76 3464gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
3891cee2 3465 forall_info * nested_forall_info, stmtblock_t * block)
6de9cd9a 3466{
3891cee2
RS
3467 stmtblock_t inner_size_body;
3468 tree inner_size, size;
3469 gfc_ss *lss, *rss;
3470 tree mask_type;
6de9cd9a
DN
3471 gfc_expr *expr1;
3472 gfc_expr *expr2;
3473 gfc_code *cblock;
3474 gfc_code *cnext;
3891cee2 3475 tree tmp;
ae772c2d 3476 tree cond;
6de9cd9a 3477 tree count1, count2;
011daa76
RS
3478 bool need_cmask;
3479 bool need_pmask;
6de9cd9a 3480 int need_temp;
3891cee2
RS
3481 tree pcmask = NULL_TREE;
3482 tree ppmask = NULL_TREE;
3483 tree cmask = NULL_TREE;
3484 tree pmask = NULL_TREE;
a00b8d1a 3485 gfc_actual_arglist *arg;
6de9cd9a
DN
3486
3487 /* the WHERE statement or the WHERE construct statement. */
3488 cblock = code->block;
3891cee2 3489
3891cee2
RS
3490 /* As the mask array can be very big, prefer compact boolean types. */
3491 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3492
011daa76
RS
3493 /* Determine which temporary masks are needed. */
3494 if (!cblock->block)
90f58ec8 3495 {
011daa76
RS
3496 /* One clause: No ELSEWHEREs. */
3497 need_cmask = (cblock->next != 0);
3498 need_pmask = false;
90f58ec8 3499 }
011daa76 3500 else if (cblock->block->block)
90f58ec8 3501 {
011daa76
RS
3502 /* Three or more clauses: Conditional ELSEWHEREs. */
3503 need_cmask = true;
3504 need_pmask = true;
90f58ec8 3505 }
011daa76
RS
3506 else if (cblock->next)
3507 {
3508 /* Two clauses, the first non-empty. */
3509 need_cmask = true;
3510 need_pmask = (mask != NULL_TREE
3511 && cblock->block->next != 0);
3512 }
3513 else if (!cblock->block->next)
3891cee2 3514 {
011daa76
RS
3515 /* Two clauses, both empty. */
3516 need_cmask = false;
3517 need_pmask = false;
3518 }
3519 /* Two clauses, the first empty, the second non-empty. */
3520 else if (mask)
3521 {
3522 need_cmask = (cblock->block->expr != 0);
3523 need_pmask = true;
3891cee2
RS
3524 }
3525 else
3526 {
011daa76
RS
3527 need_cmask = true;
3528 need_pmask = false;
3529 }
3530
3531 if (need_cmask || need_pmask)
3532 {
3533 /* Calculate the size of temporary needed by the mask-expr. */
3534 gfc_init_block (&inner_size_body);
3535 inner_size = compute_inner_temp_size (cblock->expr, cblock->expr,
3536 &inner_size_body, &lss, &rss);
3537
3538 /* Calculate the total size of temporary needed. */
3539 size = compute_overall_iter_number (nested_forall_info, inner_size,
3540 &inner_size_body, block);
3541
ae772c2d
PT
3542 /* Check whether the size is negative. */
3543 cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3544 gfc_index_zero_node);
3545 size = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
3546 gfc_index_zero_node, size);
3547 size = gfc_evaluate_now (size, block);
3548
011daa76
RS
3549 /* Allocate temporary for WHERE mask if needed. */
3550 if (need_cmask)
3551 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
3552 &pcmask);
3553
3554 /* Allocate temporary for !mask if needed. */
3555 if (need_pmask)
3556 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
3557 &ppmask);
3891cee2
RS
3558 }
3559
6de9cd9a
DN
3560 while (cblock)
3561 {
011daa76
RS
3562 /* Each time around this loop, the where clause is conditional
3563 on the value of mask and invert, which are updated at the
3564 bottom of the loop. */
3565
6de9cd9a
DN
3566 /* Has mask-expr. */
3567 if (cblock->expr)
3568 {
90f58ec8
RS
3569 /* Ensure that the WHERE mask will be evaluated exactly once.
3570 If there are no statements in this WHERE/ELSEWHERE clause,
3571 then we don't need to update the control mask (cmask).
3572 If this is the last clause of the WHERE construct, then
3891cee2 3573 we don't need to update the pending control mask (pmask). */
011daa76
RS
3574 if (mask)
3575 gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
3576 mask, invert,
3577 cblock->next ? cmask : NULL_TREE,
3578 cblock->block ? pmask : NULL_TREE,
3579 mask_type, block);
3580 else
3581 gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
3582 NULL_TREE, false,
3583 (cblock->next || cblock->block)
3584 ? cmask : NULL_TREE,
3585 NULL_TREE, mask_type, block);
6de9cd9a 3586
011daa76 3587 invert = false;
6de9cd9a 3588 }
90f58ec8 3589 /* It's a final elsewhere-stmt. No mask-expr is present. */
6de9cd9a 3590 else
3891cee2 3591 cmask = mask;
6de9cd9a 3592
011daa76
RS
3593 /* The body of this where clause are controlled by cmask with
3594 sense specified by invert. */
3595
6de9cd9a
DN
3596 /* Get the assignment statement of a WHERE statement, or the first
3597 statement in where-body-construct of a WHERE construct. */
3598 cnext = cblock->next;
3599 while (cnext)
3600 {
3601 switch (cnext->op)
3602 {
3603 /* WHERE assignment statement. */
a00b8d1a
PT
3604 case EXEC_ASSIGN_CALL:
3605
3606 arg = cnext->ext.actual;
3607 expr1 = expr2 = NULL;
3608 for (; arg; arg = arg->next)
3609 {
3610 if (!arg->expr)
3611 continue;
3612 if (expr1 == NULL)
3613 expr1 = arg->expr;
3614 else
3615 expr2 = arg->expr;
3616 }
3617 goto evaluate;
3618
6de9cd9a
DN
3619 case EXEC_ASSIGN:
3620 expr1 = cnext->expr;
3621 expr2 = cnext->expr2;
a00b8d1a 3622 evaluate:
6de9cd9a
DN
3623 if (nested_forall_info != NULL)
3624 {
3ded6210 3625 need_temp = gfc_check_dependency (expr1, expr2, 0);
a00b8d1a 3626 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
011daa76
RS
3627 gfc_trans_assign_need_temp (expr1, expr2,
3628 cmask, invert,
6de9cd9a
DN
3629 nested_forall_info, block);
3630 else
3631 {
3632 /* Variables to control maskexpr. */
3633 count1 = gfc_create_var (gfc_array_index_type, "count1");
3634 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
3635 gfc_add_modify (block, count1, gfc_index_zero_node);
3636 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 3637
011daa76
RS
3638 tmp = gfc_trans_where_assign (expr1, expr2,
3639 cmask, invert,
a00b8d1a 3640 count1, count2,
eb74e79b 3641 cnext);
8de1f441 3642
6de9cd9a 3643 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
bfcabc6c 3644 tmp, 1);
6de9cd9a
DN
3645 gfc_add_expr_to_block (block, tmp);
3646 }
3647 }
3648 else
3649 {
3650 /* Variables to control maskexpr. */
3651 count1 = gfc_create_var (gfc_array_index_type, "count1");
3652 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
3653 gfc_add_modify (block, count1, gfc_index_zero_node);
3654 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 3655
011daa76
RS
3656 tmp = gfc_trans_where_assign (expr1, expr2,
3657 cmask, invert,
a00b8d1a 3658 count1, count2,
eb74e79b 3659 cnext);
6de9cd9a
DN
3660 gfc_add_expr_to_block (block, tmp);
3661
3662 }
3663 break;
3664
3665 /* WHERE or WHERE construct is part of a where-body-construct. */
3666 case EXEC_WHERE:
011daa76
RS
3667 gfc_trans_where_2 (cnext, cmask, invert,
3668 nested_forall_info, block);
3891cee2 3669 break;
6de9cd9a
DN
3670
3671 default:
6e45f57b 3672 gcc_unreachable ();
6de9cd9a
DN
3673 }
3674
3675 /* The next statement within the same where-body-construct. */
3676 cnext = cnext->next;
3677 }
3678 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
3679 cblock = cblock->block;
011daa76
RS
3680 if (mask == NULL_TREE)
3681 {
3682 /* If we're the initial WHERE, we can simply invert the sense
3683 of the current mask to obtain the "mask" for the remaining
3684 ELSEWHEREs. */
3685 invert = true;
3686 mask = cmask;
3687 }
3688 else
3689 {
3690 /* Otherwise, for nested WHERE's we need to use the pending mask. */
3691 invert = false;
3692 mask = pmask;
3693 }
6de9cd9a 3694 }
3891cee2
RS
3695
3696 /* If we allocated a pending mask array, deallocate it now. */
3697 if (ppmask)
3698 {
1529b8d9 3699 tmp = gfc_call_free (ppmask);
3891cee2
RS
3700 gfc_add_expr_to_block (block, tmp);
3701 }
3702
3703 /* If we allocated a current mask array, deallocate it now. */
3704 if (pcmask)
3705 {
1529b8d9 3706 tmp = gfc_call_free (pcmask);
3891cee2
RS
3707 gfc_add_expr_to_block (block, tmp);
3708 }
6de9cd9a
DN
3709}
3710
3ded6210
RS
3711/* Translate a simple WHERE construct or statement without dependencies.
3712 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
3713 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
3714 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
3715
3716static tree
3717gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
3718{
3719 stmtblock_t block, body;
3720 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
3721 tree tmp, cexpr, tstmt, estmt;
3722 gfc_ss *css, *tdss, *tsss;
3723 gfc_se cse, tdse, tsse, edse, esse;
3724 gfc_loopinfo loop;
3725 gfc_ss *edss = 0;
3726 gfc_ss *esss = 0;
3727
34d01e1d
VL
3728 /* Allow the scalarizer to workshare simple where loops. */
3729 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
3730 ompws_flags |= OMPWS_SCALARIZER_WS;
3731
3ded6210
RS
3732 cond = cblock->expr;
3733 tdst = cblock->next->expr;
3734 tsrc = cblock->next->expr2;
3735 edst = eblock ? eblock->next->expr : NULL;
3736 esrc = eblock ? eblock->next->expr2 : NULL;
3737
3738 gfc_start_block (&block);
3739 gfc_init_loopinfo (&loop);
3740
3741 /* Handle the condition. */
3742 gfc_init_se (&cse, NULL);
3743 css = gfc_walk_expr (cond);
3744 gfc_add_ss_to_loop (&loop, css);
3745
3746 /* Handle the then-clause. */
3747 gfc_init_se (&tdse, NULL);
3748 gfc_init_se (&tsse, NULL);
3749 tdss = gfc_walk_expr (tdst);
3750 tsss = gfc_walk_expr (tsrc);
3751 if (tsss == gfc_ss_terminator)
3752 {
3753 tsss = gfc_get_ss ();
ae772c2d 3754 tsss->where = 1;
3ded6210
RS
3755 tsss->next = gfc_ss_terminator;
3756 tsss->type = GFC_SS_SCALAR;
3757 tsss->expr = tsrc;
3758 }
3759 gfc_add_ss_to_loop (&loop, tdss);
3760 gfc_add_ss_to_loop (&loop, tsss);
3761
3762 if (eblock)
3763 {
3764 /* Handle the else clause. */
3765 gfc_init_se (&edse, NULL);
3766 gfc_init_se (&esse, NULL);
3767 edss = gfc_walk_expr (edst);
3768 esss = gfc_walk_expr (esrc);
3769 if (esss == gfc_ss_terminator)
3770 {
3771 esss = gfc_get_ss ();
ae772c2d 3772 esss->where = 1;
3ded6210
RS
3773 esss->next = gfc_ss_terminator;
3774 esss->type = GFC_SS_SCALAR;
3775 esss->expr = esrc;
3776 }
3777 gfc_add_ss_to_loop (&loop, edss);
3778 gfc_add_ss_to_loop (&loop, esss);
3779 }
3780
3781 gfc_conv_ss_startstride (&loop);
bdfd2ff0 3782 gfc_conv_loop_setup (&loop, &tdst->where);
3ded6210
RS
3783
3784 gfc_mark_ss_chain_used (css, 1);
3785 gfc_mark_ss_chain_used (tdss, 1);
3786 gfc_mark_ss_chain_used (tsss, 1);
3787 if (eblock)
3788 {
3789 gfc_mark_ss_chain_used (edss, 1);
3790 gfc_mark_ss_chain_used (esss, 1);
3791 }
3792
3793 gfc_start_scalarized_body (&loop, &body);
3794
3795 gfc_copy_loopinfo_to_se (&cse, &loop);
3796 gfc_copy_loopinfo_to_se (&tdse, &loop);
3797 gfc_copy_loopinfo_to_se (&tsse, &loop);
3798 cse.ss = css;
3799 tdse.ss = tdss;
3800 tsse.ss = tsss;
3801 if (eblock)
3802 {
3803 gfc_copy_loopinfo_to_se (&edse, &loop);
3804 gfc_copy_loopinfo_to_se (&esse, &loop);
3805 edse.ss = edss;
3806 esse.ss = esss;
3807 }
3808
3809 gfc_conv_expr (&cse, cond);
3810 gfc_add_block_to_block (&body, &cse.pre);
3811 cexpr = cse.expr;
3812
3813 gfc_conv_expr (&tsse, tsrc);
3814 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
3815 {
3816 gfc_conv_tmp_array_ref (&tdse);
3817 gfc_advance_se_ss_chain (&tdse);
3818 }
3819 else
3820 gfc_conv_expr (&tdse, tdst);
3821
3822 if (eblock)
3823 {
3824 gfc_conv_expr (&esse, esrc);
3825 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
3826 {
3827 gfc_conv_tmp_array_ref (&edse);
3828 gfc_advance_se_ss_chain (&edse);
3829 }
3830 else
3831 gfc_conv_expr (&edse, edst);
3832 }
3833
5046aff5
PT
3834 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false);
3835 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false, false)
3ded6210
RS
3836 : build_empty_stmt ();
3837 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
3838 gfc_add_expr_to_block (&body, tmp);
3839 gfc_add_block_to_block (&body, &cse.post);
3840
3841 gfc_trans_scalarizing_loops (&loop, &body);
3842 gfc_add_block_to_block (&block, &loop.pre);
3843 gfc_add_block_to_block (&block, &loop.post);
3844 gfc_cleanup_loop (&loop);
3845
3846 return gfc_finish_block (&block);
3847}
6de9cd9a
DN
3848
3849/* As the WHERE or WHERE construct statement can be nested, we call
3850 gfc_trans_where_2 to do the translation, and pass the initial
f7b529fa 3851 NULL values for both the control mask and the pending control mask. */
6de9cd9a
DN
3852
3853tree
3854gfc_trans_where (gfc_code * code)
3855{
3856 stmtblock_t block;
3ded6210
RS
3857 gfc_code *cblock;
3858 gfc_code *eblock;
6de9cd9a 3859
3ded6210
RS
3860 cblock = code->block;
3861 if (cblock->next
3862 && cblock->next->op == EXEC_ASSIGN
3863 && !cblock->next->next)
3864 {
3865 eblock = cblock->block;
3866 if (!eblock)
3867 {
3868 /* A simple "WHERE (cond) x = y" statement or block is
3869 dependence free if cond is not dependent upon writing x,
3870 and the source y is unaffected by the destination x. */
3871 if (!gfc_check_dependency (cblock->next->expr,
3872 cblock->expr, 0)
3873 && !gfc_check_dependency (cblock->next->expr,
3874 cblock->next->expr2, 0))
3875 return gfc_trans_where_3 (cblock, NULL);
3876 }
3877 else if (!eblock->expr
3878 && !eblock->block
3879 && eblock->next
3880 && eblock->next->op == EXEC_ASSIGN
3881 && !eblock->next->next)
3882 {
3883 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
3884 block is dependence free if cond is not dependent on writes
3885 to x1 and x2, y1 is not dependent on writes to x2, and y2
3886 is not dependent on writes to x1, and both y's are not
ae772c2d
PT
3887 dependent upon their own x's. In addition to this, the
3888 final two dependency checks below exclude all but the same
3889 array reference if the where and elswhere destinations
3890 are the same. In short, this is VERY conservative and this
3891 is needed because the two loops, required by the standard
3892 are coalesced in gfc_trans_where_3. */
3ded6210
RS
3893 if (!gfc_check_dependency(cblock->next->expr,
3894 cblock->expr, 0)
3895 && !gfc_check_dependency(eblock->next->expr,
3896 cblock->expr, 0)
3897 && !gfc_check_dependency(cblock->next->expr,
ae772c2d
PT
3898 eblock->next->expr2, 1)
3899 && !gfc_check_dependency(eblock->next->expr,
3900 cblock->next->expr2, 1)
3901 && !gfc_check_dependency(cblock->next->expr,
3902 cblock->next->expr2, 1)
3ded6210 3903 && !gfc_check_dependency(eblock->next->expr,
ae772c2d 3904 eblock->next->expr2, 1)
3ded6210 3905 && !gfc_check_dependency(cblock->next->expr,
ae772c2d 3906 eblock->next->expr, 0)
3ded6210 3907 && !gfc_check_dependency(eblock->next->expr,
ae772c2d 3908 cblock->next->expr, 0))
3ded6210
RS
3909 return gfc_trans_where_3 (cblock, eblock);
3910 }
3911 }
3912
6de9cd9a 3913 gfc_start_block (&block);
6de9cd9a 3914
011daa76 3915 gfc_trans_where_2 (code, NULL, false, NULL, &block);
6de9cd9a 3916
6de9cd9a
DN
3917 return gfc_finish_block (&block);
3918}
3919
3920
3921/* CYCLE a DO loop. The label decl has already been created by
3922 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
3923 node at the head of the loop. We must mark the label as used. */
3924
3925tree
3926gfc_trans_cycle (gfc_code * code)
3927{
3928 tree cycle_label;
3929
3930 cycle_label = TREE_PURPOSE (code->ext.whichloop->backend_decl);
3931 TREE_USED (cycle_label) = 1;
3932 return build1_v (GOTO_EXPR, cycle_label);
3933}
3934
3935
e7dc5b4f 3936/* EXIT a DO loop. Similar to CYCLE, but now the label is in
6de9cd9a
DN
3937 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
3938 loop. */
3939
3940tree
3941gfc_trans_exit (gfc_code * code)
3942{
3943 tree exit_label;
3944
3945 exit_label = TREE_VALUE (code->ext.whichloop->backend_decl);
3946 TREE_USED (exit_label) = 1;
3947 return build1_v (GOTO_EXPR, exit_label);
3948}
3949
3950
3951/* Translate the ALLOCATE statement. */
3952
3953tree
3954gfc_trans_allocate (gfc_code * code)
3955{
3956 gfc_alloc *al;
3957 gfc_expr *expr;
3958 gfc_se se;
3959 tree tmp;
3960 tree parm;
6de9cd9a
DN
3961 tree stat;
3962 tree pstat;
3963 tree error_label;
3964 stmtblock_t block;
3965
3966 if (!code->ext.alloc_list)
3967 return NULL_TREE;
3968
3759634f
SK
3969 pstat = stat = error_label = tmp = NULL_TREE;
3970
6de9cd9a
DN
3971 gfc_start_block (&block);
3972
3759634f
SK
3973 /* Either STAT= and/or ERRMSG is present. */
3974 if (code->expr || code->expr2)
6de9cd9a 3975 {
e2cad04b
RH
3976 tree gfc_int4_type_node = gfc_get_int_type (4);
3977
6de9cd9a 3978 stat = gfc_create_var (gfc_int4_type_node, "stat");
628c189e 3979 pstat = gfc_build_addr_expr (NULL_TREE, stat);
6de9cd9a
DN
3980
3981 error_label = gfc_build_label_decl (NULL_TREE);
3982 TREE_USED (error_label) = 1;
3983 }
6de9cd9a
DN
3984
3985 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3986 {
3987 expr = al->expr;
3988
3989 gfc_init_se (&se, NULL);
3990 gfc_start_block (&se.pre);
3991
3992 se.want_pointer = 1;
3993 se.descriptor_only = 1;
3994 gfc_conv_expr (&se, expr);
3995
5b725b8d 3996 if (!gfc_array_allocate (&se, expr, pstat))
6de9cd9a
DN
3997 {
3998 /* A scalar or derived type. */
6de9cd9a 3999 tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
c4bbc105
PT
4000
4001 if (expr->ts.type == BT_CHARACTER && tmp == NULL_TREE)
4002 tmp = se.string_length;
4003
4376b7cf 4004 tmp = gfc_allocate_with_status (&se.pre, tmp, pstat);
44855d8c
TS
4005 tmp = fold_build2 (MODIFY_EXPR, void_type_node, se.expr,
4006 fold_convert (TREE_TYPE (se.expr), tmp));
6de9cd9a
DN
4007 gfc_add_expr_to_block (&se.pre, tmp);
4008
3759634f 4009 if (code->expr || code->expr2)
6de9cd9a
DN
4010 {
4011 tmp = build1_v (GOTO_EXPR, error_label);
61ead135
RG
4012 parm = fold_build2 (NE_EXPR, boolean_type_node,
4013 stat, build_int_cst (TREE_TYPE (stat), 0));
4014 tmp = fold_build3 (COND_EXPR, void_type_node,
4015 parm, tmp, build_empty_stmt ());
6de9cd9a
DN
4016 gfc_add_expr_to_block (&se.pre, tmp);
4017 }
5046aff5
PT
4018
4019 if (expr->ts.type == BT_DERIVED && expr->ts.derived->attr.alloc_comp)
4020 {
4021 tmp = build_fold_indirect_ref (se.expr);
4022 tmp = gfc_nullify_alloc_comp (expr->ts.derived, tmp, 0);
4023 gfc_add_expr_to_block (&se.pre, tmp);
4024 }
4025
6de9cd9a
DN
4026 }
4027
4028 tmp = gfc_finish_block (&se.pre);
4029 gfc_add_expr_to_block (&block, tmp);
4030 }
4031
3759634f 4032 /* STAT block. */
6de9cd9a
DN
4033 if (code->expr)
4034 {
4035 tmp = build1_v (LABEL_EXPR, error_label);
4036 gfc_add_expr_to_block (&block, tmp);
4037
4038 gfc_init_se (&se, NULL);
4039 gfc_conv_expr_lhs (&se, code->expr);
4040 tmp = convert (TREE_TYPE (se.expr), stat);
726a989a 4041 gfc_add_modify (&block, se.expr, tmp);
6de9cd9a
DN
4042 }
4043
3759634f
SK
4044 /* ERRMSG block. */
4045 if (code->expr2)
4046 {
4047 /* A better error message may be possible, but not required. */
4048 const char *msg = "Attempt to allocate an allocated object";
4049 tree errmsg, slen, dlen;
4050
4051 gfc_init_se (&se, NULL);
4052 gfc_conv_expr_lhs (&se, code->expr2);
4053
4054 errmsg = gfc_create_var (pchar_type_node, "ERRMSG");
4055
4056 gfc_add_modify (&block, errmsg,
4057 gfc_build_addr_expr (pchar_type_node,
4058 gfc_build_localized_cstring_const (msg)));
4059
4060 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
4061 dlen = gfc_get_expr_charlen (code->expr2);
4062 slen = fold_build2 (MIN_EXPR, TREE_TYPE (slen), dlen, slen);
4063
4064 dlen = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
4065 gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
4066
4067 tmp = fold_build2 (NE_EXPR, boolean_type_node, stat,
4068 build_int_cst (TREE_TYPE (stat), 0));
4069
4070 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt ());
4071
4072 gfc_add_expr_to_block (&block, tmp);
4073 }
4074
6de9cd9a
DN
4075 return gfc_finish_block (&block);
4076}
4077
4078
3759634f
SK
4079/* Translate a DEALLOCATE statement. */
4080
6de9cd9a 4081tree
3759634f 4082gfc_trans_deallocate (gfc_code *code)
6de9cd9a
DN
4083{
4084 gfc_se se;
4085 gfc_alloc *al;
4086 gfc_expr *expr;
5039610b 4087 tree apstat, astat, pstat, stat, tmp;
6de9cd9a
DN
4088 stmtblock_t block;
4089
3759634f
SK
4090 pstat = apstat = stat = astat = tmp = NULL_TREE;
4091
6de9cd9a
DN
4092 gfc_start_block (&block);
4093
3759634f
SK
4094 /* Count the number of failed deallocations. If deallocate() was
4095 called with STAT= , then set STAT to the count. If deallocate
4096 was called with ERRMSG, then set ERRMG to a string. */
4097 if (code->expr || code->expr2)
364667a1
SK
4098 {
4099 tree gfc_int4_type_node = gfc_get_int_type (4);
4100
364667a1 4101 stat = gfc_create_var (gfc_int4_type_node, "stat");
628c189e 4102 pstat = gfc_build_addr_expr (NULL_TREE, stat);
364667a1
SK
4103
4104 /* Running total of possible deallocation failures. */
4105 astat = gfc_create_var (gfc_int4_type_node, "astat");
628c189e 4106 apstat = gfc_build_addr_expr (NULL_TREE, astat);
364667a1
SK
4107
4108 /* Initialize astat to 0. */
726a989a 4109 gfc_add_modify (&block, astat, build_int_cst (TREE_TYPE (astat), 0));
364667a1 4110 }
364667a1 4111
6de9cd9a
DN
4112 for (al = code->ext.alloc_list; al != NULL; al = al->next)
4113 {
4114 expr = al->expr;
6e45f57b 4115 gcc_assert (expr->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
4116
4117 gfc_init_se (&se, NULL);
4118 gfc_start_block (&se.pre);
4119
4120 se.want_pointer = 1;
4121 se.descriptor_only = 1;
4122 gfc_conv_expr (&se, expr);
4123
3759634f 4124 if (expr->ts.type == BT_DERIVED && expr->ts.derived->attr.alloc_comp)
5046aff5
PT
4125 {
4126 gfc_ref *ref;
4127 gfc_ref *last = NULL;
4128 for (ref = expr->ref; ref; ref = ref->next)
4129 if (ref->type == REF_COMPONENT)
4130 last = ref;
4131
4132 /* Do not deallocate the components of a derived type
4133 ultimate pointer component. */
d4b7d0f0 4134 if (!(last && last->u.c.component->attr.pointer)
3759634f 4135 && !(!last && expr->symtree->n.sym->attr.pointer))
5046aff5
PT
4136 {
4137 tmp = gfc_deallocate_alloc_comp (expr->ts.derived, se.expr,
f25a62a5 4138 expr->rank);
5046aff5
PT
4139 gfc_add_expr_to_block (&se.pre, tmp);
4140 }
4141 }
4142
4c46bf2e 4143 if (expr->rank)
f25a62a5 4144 tmp = gfc_array_deallocate (se.expr, pstat, expr);
6de9cd9a
DN
4145 else
4146 {
f25a62a5 4147 tmp = gfc_deallocate_with_status (se.expr, pstat, false, expr);
54200abb
RG
4148 gfc_add_expr_to_block (&se.pre, tmp);
4149
44855d8c
TS
4150 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
4151 se.expr, build_int_cst (TREE_TYPE (se.expr), 0));
6de9cd9a 4152 }
364667a1
SK
4153
4154 gfc_add_expr_to_block (&se.pre, tmp);
4155
4156 /* Keep track of the number of failed deallocations by adding stat
4157 of the last deallocation to the running total. */
3759634f 4158 if (code->expr || code->expr2)
364667a1 4159 {
44855d8c 4160 apstat = fold_build2 (PLUS_EXPR, TREE_TYPE (stat), astat, stat);
726a989a 4161 gfc_add_modify (&se.pre, astat, apstat);
364667a1
SK
4162 }
4163
6de9cd9a
DN
4164 tmp = gfc_finish_block (&se.pre);
4165 gfc_add_expr_to_block (&block, tmp);
364667a1
SK
4166
4167 }
4168
3759634f 4169 /* Set STAT. */
364667a1
SK
4170 if (code->expr)
4171 {
4172 gfc_init_se (&se, NULL);
4173 gfc_conv_expr_lhs (&se, code->expr);
4174 tmp = convert (TREE_TYPE (se.expr), astat);
726a989a 4175 gfc_add_modify (&block, se.expr, tmp);
6de9cd9a
DN
4176 }
4177
3759634f
SK
4178 /* Set ERRMSG. */
4179 if (code->expr2)
4180 {
4181 /* A better error message may be possible, but not required. */
4182 const char *msg = "Attempt to deallocate an unallocated object";
4183 tree errmsg, slen, dlen;
4184
4185 gfc_init_se (&se, NULL);
4186 gfc_conv_expr_lhs (&se, code->expr2);
4187
4188 errmsg = gfc_create_var (pchar_type_node, "ERRMSG");
4189
4190 gfc_add_modify (&block, errmsg,
4191 gfc_build_addr_expr (pchar_type_node,
4192 gfc_build_localized_cstring_const (msg)));
4193
4194 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
4195 dlen = gfc_get_expr_charlen (code->expr2);
4196 slen = fold_build2 (MIN_EXPR, TREE_TYPE (slen), dlen, slen);
4197
4198 dlen = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
4199 gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
4200
4201 tmp = fold_build2 (NE_EXPR, boolean_type_node, astat,
4202 build_int_cst (TREE_TYPE (astat), 0));
4203
4204 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt ());
4205
4206 gfc_add_expr_to_block (&block, tmp);
4207 }
4208
6de9cd9a
DN
4209 return gfc_finish_block (&block);
4210}
4211