]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-stmt.c
Replace enum gfc_try with bool type.
[thirdparty/gcc.git] / gcc / fortran / trans-stmt.c
CommitLineData
6de9cd9a 1/* Statement translation -- generate GCC trees from gfc_code.
d1e082c2 2 Copyright (C) 2002-2013 Free Software Foundation, Inc.
6de9cd9a
DN
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
5
9fc4d79b 6This file is part of GCC.
6de9cd9a 7
9fc4d79b
TS
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
d234d788 10Software Foundation; either version 3, or (at your option) any later
9fc4d79b 11version.
6de9cd9a 12
9fc4d79b
TS
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
6de9cd9a
DN
17
18You should have received a copy of the GNU General Public License
d234d788
NC
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
6de9cd9a
DN
21
22
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "tree.h"
6de9cd9a 27#include "gfortran.h"
dd18a33b 28#include "flags.h"
6de9cd9a
DN
29#include "trans.h"
30#include "trans-stmt.h"
31#include "trans-types.h"
32#include "trans-array.h"
33#include "trans-const.h"
34#include "arith.h"
3ded6210 35#include "dependency.h"
d2886bc7 36#include "ggc.h"
6de9cd9a 37
6de9cd9a
DN
38typedef struct iter_info
39{
40 tree var;
41 tree start;
42 tree end;
43 tree step;
44 struct iter_info *next;
45}
46iter_info;
47
6de9cd9a
DN
48typedef struct forall_info
49{
50 iter_info *this_loop;
51 tree mask;
6de9cd9a
DN
52 tree maskindex;
53 int nvar;
54 tree size;
e8d366ec 55 struct forall_info *prev_nest;
6de9cd9a
DN
56}
57forall_info;
58
011daa76
RS
59static void gfc_trans_where_2 (gfc_code *, tree, bool,
60 forall_info *, stmtblock_t *);
6de9cd9a
DN
61
62/* Translate a F95 label number to a LABEL_EXPR. */
63
64tree
65gfc_trans_label_here (gfc_code * code)
66{
67 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
68}
69
ce2df7c6
FW
70
71/* Given a variable expression which has been ASSIGNed to, find the decl
72 containing the auxiliary variables. For variables in common blocks this
73 is a field_decl. */
74
75void
76gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
77{
78 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
79 gfc_conv_expr (se, expr);
80 /* Deals with variable in common block. Get the field declaration. */
81 if (TREE_CODE (se->expr) == COMPONENT_REF)
82 se->expr = TREE_OPERAND (se->expr, 1);
910450c1
FW
83 /* Deals with dummy argument. Get the parameter declaration. */
84 else if (TREE_CODE (se->expr) == INDIRECT_REF)
85 se->expr = TREE_OPERAND (se->expr, 0);
ce2df7c6
FW
86}
87
6de9cd9a 88/* Translate a label assignment statement. */
ce2df7c6 89
6de9cd9a
DN
90tree
91gfc_trans_label_assign (gfc_code * code)
92{
93 tree label_tree;
94 gfc_se se;
95 tree len;
96 tree addr;
97 tree len_tree;
6de9cd9a
DN
98 int label_len;
99
100 /* Start a new block. */
101 gfc_init_se (&se, NULL);
102 gfc_start_block (&se.pre);
a513927a 103 gfc_conv_label_variable (&se, code->expr1);
ce2df7c6 104
6de9cd9a
DN
105 len = GFC_DECL_STRING_LEN (se.expr);
106 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
107
79bd1948 108 label_tree = gfc_get_label_decl (code->label1);
6de9cd9a 109
f3e7b9d6
TB
110 if (code->label1->defined == ST_LABEL_TARGET
111 || code->label1->defined == ST_LABEL_DO_TARGET)
6de9cd9a
DN
112 {
113 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
114 len_tree = integer_minus_one_node;
115 }
116 else
117 {
79bd1948 118 gfc_expr *format = code->label1->format;
d393bbd7
FXC
119
120 label_len = format->value.character.length;
df09d1d5 121 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
d393bbd7
FXC
122 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
123 format->value.character.string);
b078dfbf 124 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
6de9cd9a
DN
125 }
126
726a989a
RB
127 gfc_add_modify (&se.pre, len, len_tree);
128 gfc_add_modify (&se.pre, addr, label_tree);
6de9cd9a
DN
129
130 return gfc_finish_block (&se.pre);
131}
132
133/* Translate a GOTO statement. */
134
135tree
136gfc_trans_goto (gfc_code * code)
137{
dd18a33b 138 locus loc = code->loc;
6de9cd9a
DN
139 tree assigned_goto;
140 tree target;
141 tree tmp;
6de9cd9a
DN
142 gfc_se se;
143
79bd1948
SK
144 if (code->label1 != NULL)
145 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
6de9cd9a
DN
146
147 /* ASSIGNED GOTO. */
148 gfc_init_se (&se, NULL);
149 gfc_start_block (&se.pre);
a513927a 150 gfc_conv_label_variable (&se, code->expr1);
6de9cd9a 151 tmp = GFC_DECL_STRING_LEN (se.expr);
bc98ed60
TB
152 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
153 build_int_cst (TREE_TYPE (tmp), -1));
0d52899f 154 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
c8fe94c7 155 "Assigned label is not a target label");
6de9cd9a
DN
156
157 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
6de9cd9a 158
916bd5f0
DK
159 /* We're going to ignore a label list. It does not really change the
160 statement's semantics (because it is just a further restriction on
161 what's legal code); before, we were comparing label addresses here, but
162 that's a very fragile business and may break with optimization. So
163 just ignore it. */
164
bc98ed60
TB
165 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
166 assigned_goto);
916bd5f0
DK
167 gfc_add_expr_to_block (&se.pre, target);
168 return gfc_finish_block (&se.pre);
6de9cd9a
DN
169}
170
171
3d79abbd
PB
172/* Translate an ENTRY statement. Just adds a label for this entry point. */
173tree
174gfc_trans_entry (gfc_code * code)
175{
176 return build1_v (LABEL_EXPR, code->ext.entry->label);
177}
178
179
fafcf9e6
MM
180/* Replace a gfc_ss structure by another both in the gfc_se struct
181 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
182 to replace a variable ss by the corresponding temporary. */
183
184static void
185replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
186{
187 gfc_ss **sess, **loopss;
188
189 /* The old_ss is a ss for a single variable. */
190 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
191
192 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
193 if (*sess == old_ss)
194 break;
195 gcc_assert (*sess != gfc_ss_terminator);
196
197 *sess = new_ss;
198 new_ss->next = old_ss->next;
199
200
201 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
202 loopss = &((*loopss)->loop_chain))
203 if (*loopss == old_ss)
204 break;
205 gcc_assert (*loopss != gfc_ss_terminator);
206
207 *loopss = new_ss;
208 new_ss->loop_chain = old_ss->loop_chain;
209 new_ss->loop = old_ss->loop;
210
211 gfc_free_ss (old_ss);
212}
213
214
476220e7
PT
215/* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
216 elemental subroutines. Make temporaries for output arguments if any such
217 dependencies are found. Output arguments are chosen because internal_unpack
218 can be used, as is, to copy the result back to the variable. */
219static void
220gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
2b0bd714
MM
221 gfc_symbol * sym, gfc_actual_arglist * arg,
222 gfc_dep_check check_variable)
476220e7
PT
223{
224 gfc_actual_arglist *arg0;
225 gfc_expr *e;
226 gfc_formal_arglist *formal;
476220e7
PT
227 gfc_se parmse;
228 gfc_ss *ss;
476220e7 229 gfc_symbol *fsym;
476220e7 230 tree data;
476220e7
PT
231 tree size;
232 tree tmp;
233
234 if (loopse->ss == NULL)
235 return;
236
237 ss = loopse->ss;
238 arg0 = arg;
4cbc9039 239 formal = gfc_sym_get_dummy_args (sym);
476220e7
PT
240
241 /* Loop over all the arguments testing for dependencies. */
242 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
243 {
244 e = arg->expr;
245 if (e == NULL)
246 continue;
247
8b704316 248 /* Obtain the info structure for the current argument. */
476220e7 249 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
fafcf9e6 250 if (ss->info->expr == e)
476220e7 251 break;
476220e7
PT
252
253 /* If there is a dependency, create a temporary and use it
66e4ab31 254 instead of the variable. */
476220e7
PT
255 fsym = formal ? formal->sym : NULL;
256 if (e->expr_type == EXPR_VARIABLE
257 && e->rank && fsym
06bcd751
PT
258 && fsym->attr.intent != INTENT_IN
259 && gfc_check_fncall_dependency (e, fsym->attr.intent,
2b0bd714 260 sym, arg0, check_variable))
476220e7 261 {
79e5286c 262 tree initial, temptype;
12f681a0 263 stmtblock_t temp_post;
fafcf9e6 264 gfc_ss *tmp_ss;
12f681a0 265
fafcf9e6
MM
266 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
267 GFC_SS_SECTION);
268 gfc_mark_ss_chain_used (tmp_ss, 1);
269 tmp_ss->info->expr = ss->info->expr;
270 replace_ss (loopse, ss, tmp_ss);
476220e7 271
12f681a0
DK
272 /* Obtain the argument descriptor for unpacking. */
273 gfc_init_se (&parmse, NULL);
274 parmse.want_pointer = 1;
2960a368 275 gfc_conv_expr_descriptor (&parmse, e);
12f681a0
DK
276 gfc_add_block_to_block (&se->pre, &parmse.pre);
277
eb74e79b
PT
278 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
279 initialize the array temporary with a copy of the values. */
280 if (fsym->attr.intent == INTENT_INOUT
281 || (fsym->ts.type ==BT_DERIVED
282 && fsym->attr.intent == INTENT_OUT))
12f681a0 283 initial = parmse.expr;
866e6d1b
PT
284 /* For class expressions, we always initialize with the copy of
285 the values. */
286 else if (e->ts.type == BT_CLASS)
287 initial = parmse.expr;
12f681a0
DK
288 else
289 initial = NULL_TREE;
290
866e6d1b
PT
291 if (e->ts.type != BT_CLASS)
292 {
293 /* Find the type of the temporary to create; we don't use the type
294 of e itself as this breaks for subcomponent-references in e
295 (where the type of e is that of the final reference, but
296 parmse.expr's type corresponds to the full derived-type). */
297 /* TODO: Fix this somehow so we don't need a temporary of the whole
298 array but instead only the components referenced. */
299 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
300 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
301 temptype = TREE_TYPE (temptype);
302 temptype = gfc_get_element_type (temptype);
303 }
304
305 else
306 /* For class arrays signal that the size of the dynamic type has to
307 be obtained from the vtable, using the 'initial' expression. */
308 temptype = NULL_TREE;
79e5286c
DK
309
310 /* Generate the temporary. Cleaning up the temporary should be the
311 very last thing done, so we add the code to a new block and add it
312 to se->post as last instructions. */
476220e7
PT
313 size = gfc_create_var (gfc_array_index_type, NULL);
314 data = gfc_create_var (pvoid_type_node, NULL);
12f681a0 315 gfc_init_block (&temp_post);
fafcf9e6 316 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
41645793
MM
317 temptype, initial, false, true,
318 false, &arg->expr->where);
726a989a 319 gfc_add_modify (&se->pre, size, tmp);
fafcf9e6 320 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
726a989a 321 gfc_add_modify (&se->pre, data, tmp);
476220e7 322
fafcf9e6
MM
323 /* Update other ss' delta. */
324 gfc_set_delta (loopse->loop);
476220e7 325
866e6d1b
PT
326 /* Copy the result back using unpack..... */
327 if (e->ts.type != BT_CLASS)
328 tmp = build_call_expr_loc (input_location,
329 gfor_fndecl_in_unpack, 2, parmse.expr, data);
330 else
331 {
332 /* ... except for class results where the copy is
333 unconditional. */
334 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
335 tmp = gfc_conv_descriptor_data_get (tmp);
336 tmp = build_call_expr_loc (input_location,
337 builtin_decl_explicit (BUILT_IN_MEMCPY),
ee4b6b52
JJ
338 3, tmp, data,
339 fold_convert (size_type_node, size));
866e6d1b 340 }
476220e7
PT
341 gfc_add_expr_to_block (&se->post, tmp);
342
79e5286c 343 /* parmse.pre is already added above. */
476220e7 344 gfc_add_block_to_block (&se->post, &parmse.post);
12f681a0 345 gfc_add_block_to_block (&se->post, &temp_post);
476220e7
PT
346 }
347 }
348}
349
350
9436b221
MM
351/* Get the interface symbol for the procedure corresponding to the given call.
352 We can't get the procedure symbol directly as we have to handle the case
353 of (deferred) type-bound procedures. */
354
355static gfc_symbol *
356get_proc_ifc_for_call (gfc_code *c)
357{
358 gfc_symbol *sym;
359
360 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
361
362 sym = gfc_get_proc_ifc_for_expr (c->expr1);
363
364 /* Fall back/last resort try. */
365 if (sym == NULL)
366 sym = c->resolved_sym;
367
368 return sym;
369}
370
371
6de9cd9a
DN
372/* Translate the CALL statement. Builds a call to an F95 subroutine. */
373
374tree
eb74e79b
PT
375gfc_trans_call (gfc_code * code, bool dependency_check,
376 tree mask, tree count1, bool invert)
6de9cd9a
DN
377{
378 gfc_se se;
48474141 379 gfc_ss * ss;
dda895f9 380 int has_alternate_specifier;
2b0bd714 381 gfc_dep_check check_variable;
eb74e79b
PT
382 tree index = NULL_TREE;
383 tree maskexpr = NULL_TREE;
384 tree tmp;
6de9cd9a
DN
385
386 /* A CALL starts a new block because the actual arguments may have to
387 be evaluated first. */
388 gfc_init_se (&se, NULL);
389 gfc_start_block (&se.pre);
390
6e45f57b 391 gcc_assert (code->resolved_sym);
6de9cd9a 392
48474141
PT
393 ss = gfc_ss_terminator;
394 if (code->resolved_sym->attr.elemental)
17d038cd 395 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
9436b221 396 get_proc_ifc_for_call (code),
dec131b6 397 GFC_SS_REFERENCE);
6de9cd9a 398
48474141
PT
399 /* Is not an elemental subroutine call with array valued arguments. */
400 if (ss == gfc_ss_terminator)
6de9cd9a 401 {
48474141
PT
402
403 /* Translate the call. */
404 has_alternate_specifier
713485cc 405 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
989ea525 406 code->expr1, NULL);
48474141
PT
407
408 /* A subroutine without side-effect, by definition, does nothing! */
409 TREE_SIDE_EFFECTS (se.expr) = 1;
410
411 /* Chain the pieces together and return the block. */
412 if (has_alternate_specifier)
413 {
414 gfc_code *select_code;
415 gfc_symbol *sym;
416 select_code = code->next;
417 gcc_assert(select_code->op == EXEC_SELECT);
a513927a 418 sym = select_code->expr1->symtree->n.sym;
48474141 419 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
9ebe2d22
PT
420 if (sym->backend_decl == NULL)
421 sym->backend_decl = gfc_get_symbol_decl (sym);
726a989a 422 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
48474141
PT
423 }
424 else
425 gfc_add_expr_to_block (&se.pre, se.expr);
426
427 gfc_add_block_to_block (&se.pre, &se.post);
6de9cd9a 428 }
48474141 429
6de9cd9a 430 else
48474141
PT
431 {
432 /* An elemental subroutine call with array valued arguments has
433 to be scalarized. */
434 gfc_loopinfo loop;
435 stmtblock_t body;
436 stmtblock_t block;
437 gfc_se loopse;
70e72065 438 gfc_se depse;
48474141
PT
439
440 /* gfc_walk_elemental_function_args renders the ss chain in the
12f681a0 441 reverse order to the actual argument order. */
48474141
PT
442 ss = gfc_reverse_ss (ss);
443
444 /* Initialize the loop. */
445 gfc_init_se (&loopse, NULL);
446 gfc_init_loopinfo (&loop);
447 gfc_add_ss_to_loop (&loop, ss);
448
449 gfc_conv_ss_startstride (&loop);
8b704316
PT
450 /* TODO: gfc_conv_loop_setup generates a temporary for vector
451 subscripts. This could be prevented in the elemental case
452 as temporaries are handled separatedly
2b0bd714 453 (below in gfc_conv_elemental_dependencies). */
a513927a 454 gfc_conv_loop_setup (&loop, &code->expr1->where);
48474141
PT
455 gfc_mark_ss_chain_used (ss, 1);
456
476220e7
PT
457 /* Convert the arguments, checking for dependencies. */
458 gfc_copy_loopinfo_to_se (&loopse, &loop);
459 loopse.ss = ss;
460
06bcd751 461 /* For operator assignment, do dependency checking. */
476220e7 462 if (dependency_check)
2b0bd714
MM
463 check_variable = ELEM_CHECK_VARIABLE;
464 else
465 check_variable = ELEM_DONT_CHECK_VARIABLE;
70e72065
MM
466
467 gfc_init_se (&depse, NULL);
468 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
2b0bd714 469 code->ext.actual, check_variable);
476220e7 470
70e72065
MM
471 gfc_add_block_to_block (&loop.pre, &depse.pre);
472 gfc_add_block_to_block (&loop.post, &depse.post);
473
48474141
PT
474 /* Generate the loop body. */
475 gfc_start_scalarized_body (&loop, &body);
476 gfc_init_block (&block);
48474141 477
eb74e79b
PT
478 if (mask && count1)
479 {
480 /* Form the mask expression according to the mask. */
481 index = count1;
482 maskexpr = gfc_build_array_ref (mask, index, NULL);
483 if (invert)
bc98ed60
TB
484 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
485 TREE_TYPE (maskexpr), maskexpr);
eb74e79b
PT
486 }
487
48474141 488 /* Add the subroutine call to the block. */
eb74e79b 489 gfc_conv_procedure_call (&loopse, code->resolved_sym,
9771b263
DN
490 code->ext.actual, code->expr1,
491 NULL);
eb74e79b
PT
492
493 if (mask && count1)
494 {
495 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
c2255bc4 496 build_empty_stmt (input_location));
eb74e79b 497 gfc_add_expr_to_block (&loopse.pre, tmp);
bc98ed60
TB
498 tmp = fold_build2_loc (input_location, PLUS_EXPR,
499 gfc_array_index_type,
500 count1, gfc_index_one_node);
eb74e79b
PT
501 gfc_add_modify (&loopse.pre, count1, tmp);
502 }
503 else
504 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
48474141
PT
505
506 gfc_add_block_to_block (&block, &loopse.pre);
507 gfc_add_block_to_block (&block, &loopse.post);
508
509 /* Finish up the loop block and the loop. */
510 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
511 gfc_trans_scalarizing_loops (&loop, &body);
512 gfc_add_block_to_block (&se.pre, &loop.pre);
513 gfc_add_block_to_block (&se.pre, &loop.post);
476220e7 514 gfc_add_block_to_block (&se.pre, &se.post);
48474141
PT
515 gfc_cleanup_loop (&loop);
516 }
6de9cd9a 517
6de9cd9a
DN
518 return gfc_finish_block (&se.pre);
519}
520
521
522/* Translate the RETURN statement. */
523
524tree
d74d8807 525gfc_trans_return (gfc_code * code)
6de9cd9a 526{
a513927a 527 if (code->expr1)
6de9cd9a
DN
528 {
529 gfc_se se;
530 tree tmp;
531 tree result;
532
da4c6ed8 533 /* If code->expr is not NULL, this return statement must appear
d74d8807 534 in a subroutine and current_fake_result_decl has already
6de9cd9a
DN
535 been generated. */
536
5f20c93a 537 result = gfc_get_fake_result_decl (NULL, 0);
6de9cd9a 538 if (!result)
d74d8807
DK
539 {
540 gfc_warning ("An alternate return at %L without a * dummy argument",
541 &code->expr1->where);
542 return gfc_generate_return ();
543 }
6de9cd9a
DN
544
545 /* Start a new block for this statement. */
546 gfc_init_se (&se, NULL);
547 gfc_start_block (&se.pre);
548
a513927a 549 gfc_conv_expr (&se, code->expr1);
6de9cd9a 550
ba3ff5c2
DK
551 /* Note that the actually returned expression is a simple value and
552 does not depend on any pointers or such; thus we can clean-up with
553 se.post before returning. */
bc98ed60
TB
554 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
555 result, fold_convert (TREE_TYPE (result),
556 se.expr));
6de9cd9a 557 gfc_add_expr_to_block (&se.pre, tmp);
ba3ff5c2 558 gfc_add_block_to_block (&se.pre, &se.post);
6de9cd9a 559
d74d8807 560 tmp = gfc_generate_return ();
6de9cd9a 561 gfc_add_expr_to_block (&se.pre, tmp);
6de9cd9a
DN
562 return gfc_finish_block (&se.pre);
563 }
d74d8807
DK
564
565 return gfc_generate_return ();
6de9cd9a
DN
566}
567
568
569/* Translate the PAUSE statement. We have to translate this statement
570 to a runtime library call. */
571
572tree
573gfc_trans_pause (gfc_code * code)
574{
e2cad04b 575 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 576 gfc_se se;
6de9cd9a 577 tree tmp;
6de9cd9a
DN
578
579 /* Start a new block for this statement. */
580 gfc_init_se (&se, NULL);
581 gfc_start_block (&se.pre);
582
583
a513927a 584 if (code->expr1 == NULL)
6de9cd9a 585 {
6d1b0f92 586 tmp = build_int_cst (gfc_int4_type_node, 0);
db3927fb 587 tmp = build_call_expr_loc (input_location,
6d1b0f92
JD
588 gfor_fndecl_pause_string, 2,
589 build_int_cst (pchar_type_node, 0), tmp);
590 }
591 else if (code->expr1->ts.type == BT_INTEGER)
592 {
593 gfc_conv_expr (&se, code->expr1);
594 tmp = build_call_expr_loc (input_location,
595 gfor_fndecl_pause_numeric, 1,
596 fold_convert (gfc_int4_type_node, se.expr));
6de9cd9a
DN
597 }
598 else
599 {
a513927a 600 gfc_conv_expr_reference (&se, code->expr1);
db3927fb
AH
601 tmp = build_call_expr_loc (input_location,
602 gfor_fndecl_pause_string, 2,
5039610b 603 se.expr, se.string_length);
6de9cd9a
DN
604 }
605
6de9cd9a
DN
606 gfc_add_expr_to_block (&se.pre, tmp);
607
608 gfc_add_block_to_block (&se.pre, &se.post);
609
610 return gfc_finish_block (&se.pre);
611}
612
613
614/* Translate the STOP statement. We have to translate this statement
615 to a runtime library call. */
616
617tree
d0a4a61c 618gfc_trans_stop (gfc_code *code, bool error_stop)
6de9cd9a 619{
e2cad04b 620 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 621 gfc_se se;
6de9cd9a 622 tree tmp;
6de9cd9a
DN
623
624 /* Start a new block for this statement. */
625 gfc_init_se (&se, NULL);
626 gfc_start_block (&se.pre);
627
60386f50
TB
628 if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
629 {
630 /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
e79983f4 631 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
60386f50
TB
632 tmp = build_call_expr_loc (input_location, tmp, 0);
633 gfc_add_expr_to_block (&se.pre, tmp);
634
635 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_finalize, 0);
636 gfc_add_expr_to_block (&se.pre, tmp);
637 }
638
a513927a 639 if (code->expr1 == NULL)
6de9cd9a 640 {
6d1b0f92
JD
641 tmp = build_int_cst (gfc_int4_type_node, 0);
642 tmp = build_call_expr_loc (input_location,
60386f50
TB
643 error_stop
644 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
645 ? gfor_fndecl_caf_error_stop_str
646 : gfor_fndecl_error_stop_string)
6d1b0f92 647 : gfor_fndecl_stop_string,
cea59ace 648 2, build_int_cst (pchar_type_node, 0), tmp);
6d1b0f92
JD
649 }
650 else if (code->expr1->ts.type == BT_INTEGER)
651 {
652 gfc_conv_expr (&se, code->expr1);
db3927fb 653 tmp = build_call_expr_loc (input_location,
60386f50
TB
654 error_stop
655 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
656 ? gfor_fndecl_caf_error_stop
657 : gfor_fndecl_error_stop_numeric)
8b704316 658 : gfor_fndecl_stop_numeric_f08, 1,
6d1b0f92 659 fold_convert (gfc_int4_type_node, se.expr));
6de9cd9a
DN
660 }
661 else
662 {
a513927a 663 gfc_conv_expr_reference (&se, code->expr1);
db3927fb 664 tmp = build_call_expr_loc (input_location,
60386f50
TB
665 error_stop
666 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
667 ? gfor_fndecl_caf_error_stop_str
668 : gfor_fndecl_error_stop_string)
6d1b0f92 669 : gfor_fndecl_stop_string,
cea59ace 670 2, se.expr, se.string_length);
6de9cd9a
DN
671 }
672
6de9cd9a
DN
673 gfc_add_expr_to_block (&se.pre, tmp);
674
675 gfc_add_block_to_block (&se.pre, &se.post);
676
677 return gfc_finish_block (&se.pre);
678}
679
680
fea54935
TB
681tree
682gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
683{
684 gfc_se se, argse;
685 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
686
687 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
688 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
689 if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
8b704316 690 return NULL_TREE;
fea54935
TB
691
692 gfc_init_se (&se, NULL);
693 gfc_start_block (&se.pre);
694
695 if (code->expr2)
696 {
697 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
698 gfc_init_se (&argse, NULL);
699 gfc_conv_expr_val (&argse, code->expr2);
700 stat = argse.expr;
701 }
702
703 if (code->expr4)
704 {
705 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
706 gfc_init_se (&argse, NULL);
707 gfc_conv_expr_val (&argse, code->expr4);
708 lock_acquired = argse.expr;
709 }
710
711 if (stat != NULL_TREE)
712 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
713
714 if (lock_acquired != NULL_TREE)
715 gfc_add_modify (&se.pre, lock_acquired,
716 fold_convert (TREE_TYPE (lock_acquired),
717 boolean_true_node));
718
719 return gfc_finish_block (&se.pre);
720}
721
722
d0a4a61c 723tree
60386f50 724gfc_trans_sync (gfc_code *code, gfc_exec_op type)
d0a4a61c 725{
60386f50
TB
726 gfc_se se, argse;
727 tree tmp;
728 tree images = NULL_TREE, stat = NULL_TREE,
729 errmsg = NULL_TREE, errmsglen = NULL_TREE;
d0a4a61c 730
60386f50
TB
731 /* Short cut: For single images without bound checking or without STAT=,
732 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
733 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
734 && gfc_option.coarray != GFC_FCOARRAY_LIB)
8b704316 735 return NULL_TREE;
60386f50
TB
736
737 gfc_init_se (&se, NULL);
738 gfc_start_block (&se.pre);
739
740 if (code->expr1 && code->expr1->rank == 0)
d0a4a61c 741 {
60386f50
TB
742 gfc_init_se (&argse, NULL);
743 gfc_conv_expr_val (&argse, code->expr1);
744 images = argse.expr;
745 }
746
747 if (code->expr2)
748 {
749 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
750 gfc_init_se (&argse, NULL);
751 gfc_conv_expr_val (&argse, code->expr2);
752 stat = argse.expr;
753 }
f5c01f5b
DC
754 else
755 stat = null_pointer_node;
60386f50
TB
756
757 if (code->expr3 && gfc_option.coarray == GFC_FCOARRAY_LIB
758 && type != EXEC_SYNC_MEMORY)
759 {
760 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
761 gfc_init_se (&argse, NULL);
762 gfc_conv_expr (&argse, code->expr3);
763 gfc_conv_string_parameter (&argse);
f5c01f5b 764 errmsg = gfc_build_addr_expr (NULL, argse.expr);
60386f50
TB
765 errmsglen = argse.string_length;
766 }
767 else if (gfc_option.coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY)
768 {
769 errmsg = null_pointer_node;
770 errmsglen = build_int_cst (integer_type_node, 0);
d0a4a61c
TB
771 }
772
773 /* Check SYNC IMAGES(imageset) for valid image index.
774 FIXME: Add a check for image-set arrays. */
775 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
776 && code->expr1->rank == 0)
777 {
778 tree cond;
60386f50
TB
779 if (gfc_option.coarray != GFC_FCOARRAY_LIB)
780 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
781 images, build_int_cst (TREE_TYPE (images), 1));
782 else
783 {
784 tree cond2;
45d5889a 785 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
60386f50
TB
786 images, gfort_gvar_caf_num_images);
787 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
788 images,
789 build_int_cst (TREE_TYPE (images), 1));
45d5889a 790 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
60386f50
TB
791 boolean_type_node, cond, cond2);
792 }
d0a4a61c
TB
793 gfc_trans_runtime_check (true, false, cond, &se.pre,
794 &code->expr1->where, "Invalid image number "
795 "%d in SYNC IMAGES",
74c49505 796 fold_convert (integer_type_node, images));
d0a4a61c
TB
797 }
798
60386f50
TB
799 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
800 image control statements SYNC IMAGES and SYNC ALL. */
801 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
802 {
e79983f4 803 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
5d81ddd0
TB
804 tmp = build_call_expr_loc (input_location, tmp, 0);
805 gfc_add_expr_to_block (&se.pre, tmp);
60386f50
TB
806 }
807
808 if (gfc_option.coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
d0a4a61c 809 {
60386f50
TB
810 /* Set STAT to zero. */
811 if (code->expr2)
812 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
813 }
814 else if (type == EXEC_SYNC_ALL)
815 {
f5c01f5b
DC
816 /* SYNC ALL => stat == null_pointer_node
817 SYNC ALL(stat=s) => stat has an integer type
818
819 If "stat" has the wrong integer type, use a temp variable of
820 the right type and later cast the result back into "stat". */
821 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
822 {
823 if (TREE_TYPE (stat) == integer_type_node)
824 stat = gfc_build_addr_expr (NULL, stat);
8b704316 825
f5c01f5b
DC
826 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
827 3, stat, errmsg, errmsglen);
828 gfc_add_expr_to_block (&se.pre, tmp);
829 }
60386f50 830 else
f5c01f5b
DC
831 {
832 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
833
834 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
835 3, gfc_build_addr_expr (NULL, tmp_stat),
836 errmsg, errmsglen);
837 gfc_add_expr_to_block (&se.pre, tmp);
8b704316 838
f5c01f5b
DC
839 gfc_add_modify (&se.pre, stat,
840 fold_convert (TREE_TYPE (stat), tmp_stat));
841 }
60386f50
TB
842 }
843 else
844 {
845 tree len;
846
847 gcc_assert (type == EXEC_SYNC_IMAGES);
848
849 if (!code->expr1)
850 {
851 len = build_int_cst (integer_type_node, -1);
852 images = null_pointer_node;
853 }
854 else if (code->expr1->rank == 0)
855 {
856 len = build_int_cst (integer_type_node, 1);
857 images = gfc_build_addr_expr (NULL_TREE, images);
858 }
859 else
860 {
861 /* FIXME. */
862 if (code->expr1->ts.kind != gfc_c_int_kind)
863 gfc_fatal_error ("Sorry, only support for integer kind %d "
864 "implemented for image-set at %L",
865 gfc_c_int_kind, &code->expr1->where);
866
2960a368 867 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
60386f50
TB
868 images = se.expr;
869
870 tmp = gfc_typenode_for_spec (&code->expr1->ts);
871 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
872 tmp = gfc_get_element_type (tmp);
873
874 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
875 TREE_TYPE (len), len,
876 fold_convert (TREE_TYPE (len),
877 TYPE_SIZE_UNIT (tmp)));
878 len = fold_convert (integer_type_node, len);
879 }
880
f5c01f5b
DC
881 /* SYNC IMAGES(imgs) => stat == null_pointer_node
882 SYNC IMAGES(imgs,stat=s) => stat has an integer type
883
884 If "stat" has the wrong integer type, use a temp variable of
885 the right type and later cast the result back into "stat". */
886 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
887 {
888 if (TREE_TYPE (stat) == integer_type_node)
889 stat = gfc_build_addr_expr (NULL, stat);
890
8b704316 891 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
f5c01f5b
DC
892 5, fold_convert (integer_type_node, len),
893 images, stat, errmsg, errmsglen);
894 gfc_add_expr_to_block (&se.pre, tmp);
895 }
60386f50 896 else
f5c01f5b
DC
897 {
898 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
899
8b704316 900 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
f5c01f5b
DC
901 5, fold_convert (integer_type_node, len),
902 images, gfc_build_addr_expr (NULL, tmp_stat),
903 errmsg, errmsglen);
904 gfc_add_expr_to_block (&se.pre, tmp);
905
8b704316 906 gfc_add_modify (&se.pre, stat,
f5c01f5b
DC
907 fold_convert (TREE_TYPE (stat), tmp_stat));
908 }
d0a4a61c
TB
909 }
910
60386f50 911 return gfc_finish_block (&se.pre);
d0a4a61c
TB
912}
913
914
6de9cd9a
DN
915/* Generate GENERIC for the IF construct. This function also deals with
916 the simple IF statement, because the front end translates the IF
917 statement into an IF construct.
918
919 We translate:
920
921 IF (cond) THEN
922 then_clause
923 ELSEIF (cond2)
924 elseif_clause
925 ELSE
926 else_clause
927 ENDIF
928
929 into:
930
931 pre_cond_s;
932 if (cond_s)
933 {
934 then_clause;
935 }
936 else
937 {
938 pre_cond_s
939 if (cond_s)
940 {
941 elseif_clause
942 }
943 else
944 {
945 else_clause;
946 }
947 }
948
949 where COND_S is the simplified version of the predicate. PRE_COND_S
950 are the pre side-effects produced by the translation of the
951 conditional.
952 We need to build the chain recursively otherwise we run into
953 problems with folding incomplete statements. */
954
955static tree
956gfc_trans_if_1 (gfc_code * code)
957{
958 gfc_se if_se;
959 tree stmt, elsestmt;
e84589e1 960 locus saved_loc;
55bd9c35 961 location_t loc;
6de9cd9a
DN
962
963 /* Check for an unconditional ELSE clause. */
a513927a 964 if (!code->expr1)
6de9cd9a
DN
965 return gfc_trans_code (code->next);
966
967 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
968 gfc_init_se (&if_se, NULL);
969 gfc_start_block (&if_se.pre);
970
971 /* Calculate the IF condition expression. */
e84589e1
TB
972 if (code->expr1->where.lb)
973 {
974 gfc_save_backend_locus (&saved_loc);
975 gfc_set_backend_locus (&code->expr1->where);
976 }
977
a513927a 978 gfc_conv_expr_val (&if_se, code->expr1);
6de9cd9a 979
e84589e1
TB
980 if (code->expr1->where.lb)
981 gfc_restore_backend_locus (&saved_loc);
982
6de9cd9a
DN
983 /* Translate the THEN clause. */
984 stmt = gfc_trans_code (code->next);
985
986 /* Translate the ELSE clause. */
987 if (code->block)
988 elsestmt = gfc_trans_if_1 (code->block);
989 else
c2255bc4 990 elsestmt = build_empty_stmt (input_location);
6de9cd9a
DN
991
992 /* Build the condition expression and add it to the condition block. */
55bd9c35
TB
993 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
994 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
995 elsestmt);
8b704316 996
6de9cd9a
DN
997 gfc_add_expr_to_block (&if_se.pre, stmt);
998
999 /* Finish off this statement. */
1000 return gfc_finish_block (&if_se.pre);
1001}
1002
1003tree
1004gfc_trans_if (gfc_code * code)
1005{
e5ca9693
DK
1006 stmtblock_t body;
1007 tree exit_label;
1008
1009 /* Create exit label so it is available for trans'ing the body code. */
1010 exit_label = gfc_build_label_decl (NULL_TREE);
1011 code->exit_label = exit_label;
1012
1013 /* Translate the actual code in code->block. */
1014 gfc_init_block (&body);
1015 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1016
1017 /* Add exit label. */
1018 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
6de9cd9a 1019
e5ca9693 1020 return gfc_finish_block (&body);
6de9cd9a
DN
1021}
1022
1023
fa951694 1024/* Translate an arithmetic IF expression.
6de9cd9a
DN
1025
1026 IF (cond) label1, label2, label3 translates to
1027
1028 if (cond <= 0)
1029 {
1030 if (cond < 0)
1031 goto label1;
1032 else // cond == 0
1033 goto label2;
1034 }
1035 else // cond > 0
1036 goto label3;
442c1644
CY
1037
1038 An optimized version can be generated in case of equal labels.
1039 E.g., if label1 is equal to label2, we can translate it to
1040
1041 if (cond <= 0)
1042 goto label1;
1043 else
1044 goto label3;
6de9cd9a
DN
1045*/
1046
1047tree
1048gfc_trans_arithmetic_if (gfc_code * code)
1049{
1050 gfc_se se;
1051 tree tmp;
1052 tree branch1;
1053 tree branch2;
1054 tree zero;
1055
1056 /* Start a new block. */
1057 gfc_init_se (&se, NULL);
1058 gfc_start_block (&se.pre);
1059
1060 /* Pre-evaluate COND. */
a513927a 1061 gfc_conv_expr_val (&se, code->expr1);
5ec1334b 1062 se.expr = gfc_evaluate_now (se.expr, &se.pre);
6de9cd9a
DN
1063
1064 /* Build something to compare with. */
1065 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1066
79bd1948 1067 if (code->label1->value != code->label2->value)
442c1644
CY
1068 {
1069 /* If (cond < 0) take branch1 else take branch2.
1070 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
79bd1948 1071 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
442c1644
CY
1072 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1073
79bd1948 1074 if (code->label1->value != code->label3->value)
bc98ed60
TB
1075 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1076 se.expr, zero);
442c1644 1077 else
bc98ed60
TB
1078 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1079 se.expr, zero);
6de9cd9a 1080
bc98ed60
TB
1081 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1082 tmp, branch1, branch2);
442c1644
CY
1083 }
1084 else
79bd1948 1085 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
6de9cd9a 1086
79bd1948 1087 if (code->label1->value != code->label3->value
442c1644
CY
1088 && code->label2->value != code->label3->value)
1089 {
1090 /* if (cond <= 0) take branch1 else take branch2. */
1091 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
bc98ed60
TB
1092 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1093 se.expr, zero);
1094 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1095 tmp, branch1, branch2);
442c1644 1096 }
6de9cd9a
DN
1097
1098 /* Append the COND_EXPR to the evaluation of COND, and return. */
1099 gfc_add_expr_to_block (&se.pre, branch1);
1100 return gfc_finish_block (&se.pre);
1101}
1102
1103
d0a4a61c
TB
1104/* Translate a CRITICAL block. */
1105tree
1106gfc_trans_critical (gfc_code *code)
1107{
1108 stmtblock_t block;
1109 tree tmp;
1110
1111 gfc_start_block (&block);
60386f50
TB
1112
1113 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1114 {
1115 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_critical, 0);
1116 gfc_add_expr_to_block (&block, tmp);
1117 }
1118
d0a4a61c
TB
1119 tmp = gfc_trans_code (code->block->next);
1120 gfc_add_expr_to_block (&block, tmp);
1121
60386f50
TB
1122 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1123 {
1124 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_critical,
1125 0);
1126 gfc_add_expr_to_block (&block, tmp);
1127 }
1128
1129
d0a4a61c
TB
1130 return gfc_finish_block (&block);
1131}
1132
1133
6312ef45
JW
1134/* Do proper initialization for ASSOCIATE names. */
1135
1136static void
1137trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1138{
1139 gfc_expr *e;
1140 tree tmp;
c49ea23d 1141 bool class_target;
8b704316 1142 bool unlimited;
8f75db9f
PT
1143 tree desc;
1144 tree offset;
1145 tree dim;
1146 int n;
6312ef45
JW
1147
1148 gcc_assert (sym->assoc);
1149 e = sym->assoc->target;
1150
c49ea23d
PT
1151 class_target = (e->expr_type == EXPR_VARIABLE)
1152 && (gfc_is_class_scalar_expr (e)
1153 || gfc_is_class_array_ref (e, NULL));
1154
8b704316
PT
1155 unlimited = UNLIMITED_POLY (e);
1156
6312ef45
JW
1157 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1158 to array temporary) for arrays with either unknown shape or if associating
1159 to a variable. */
c49ea23d 1160 if (sym->attr.dimension && !class_target
6312ef45
JW
1161 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1162 {
1163 gfc_se se;
6312ef45
JW
1164 tree desc;
1165
1166 desc = sym->backend_decl;
1167
1168 /* If association is to an expression, evaluate it and create temporary.
1169 Otherwise, get descriptor of target for pointer assignment. */
1170 gfc_init_se (&se, NULL);
6312ef45
JW
1171 if (sym->assoc->variable)
1172 {
1173 se.direct_byref = 1;
1174 se.expr = desc;
1175 }
2960a368 1176 gfc_conv_expr_descriptor (&se, e);
6312ef45
JW
1177
1178 /* If we didn't already do the pointer assignment, set associate-name
1179 descriptor to the one generated for the temporary. */
1180 if (!sym->assoc->variable)
1181 {
1182 int dim;
1183
1184 gfc_add_modify (&se.pre, desc, se.expr);
1185
1186 /* The generated descriptor has lower bound zero (as array
1187 temporary), shift bounds so we get lower bounds of 1. */
1188 for (dim = 0; dim < e->rank; ++dim)
1189 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1190 dim, gfc_index_one_node);
1191 }
1192
1193 /* Done, register stuff as init / cleanup code. */
1194 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1195 gfc_finish_block (&se.post));
1196 }
1197
8b704316
PT
1198 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1199 arrays to be assigned directly. */
1200 else if (class_target && sym->attr.dimension
1201 && (sym->ts.type == BT_DERIVED || unlimited))
c49ea23d
PT
1202 {
1203 gfc_se se;
1204
1205 gfc_init_se (&se, NULL);
102344e2 1206 se.descriptor_only = 1;
c49ea23d
PT
1207 gfc_conv_expr (&se, e);
1208
1209 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1210 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1211
1212 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
8b704316
PT
1213
1214 if (unlimited)
1215 {
1216 /* Recover the dtype, which has been overwritten by the
1217 assignment from an unlimited polymorphic object. */
1218 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1219 gfc_add_modify (&se.pre, tmp,
1220 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1221 }
1222
c49ea23d
PT
1223 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1224 gfc_finish_block (&se.post));
1225 }
1226
6312ef45
JW
1227 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1228 else if (gfc_is_associate_pointer (sym))
1229 {
1230 gfc_se se;
1231
1232 gcc_assert (!sym->attr.dimension);
1233
1234 gfc_init_se (&se, NULL);
8f75db9f
PT
1235
1236 /* Class associate-names come this way because they are
1237 unconditionally associate pointers and the symbol is scalar. */
1238 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1239 {
1240 /* For a class array we need a descriptor for the selector. */
2960a368 1241 gfc_conv_expr_descriptor (&se, e);
8f75db9f 1242
8b704316 1243 /* Obtain a temporary class container for the result. */
16e82b25 1244 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
8f75db9f
PT
1245 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1246
1247 /* Set the offset. */
1248 desc = gfc_class_data_get (se.expr);
1249 offset = gfc_index_zero_node;
1250 for (n = 0; n < e->rank; n++)
1251 {
1252 dim = gfc_rank_cst[n];
1253 tmp = fold_build2_loc (input_location, MULT_EXPR,
1254 gfc_array_index_type,
1255 gfc_conv_descriptor_stride_get (desc, dim),
1256 gfc_conv_descriptor_lbound_get (desc, dim));
1257 offset = fold_build2_loc (input_location, MINUS_EXPR,
1258 gfc_array_index_type,
1259 offset, tmp);
1260 }
1261 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1262 }
1263 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1264 && CLASS_DATA (e)->attr.dimension)
1265 {
1266 /* This is bound to be a class array element. */
1267 gfc_conv_expr_reference (&se, e);
8b704316 1268 /* Get the _vptr component of the class object. */
8f75db9f
PT
1269 tmp = gfc_get_vptr_from_expr (se.expr);
1270 /* Obtain a temporary class container for the result. */
16e82b25 1271 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
8f75db9f
PT
1272 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1273 }
1274 else
1275 gfc_conv_expr (&se, e);
6312ef45
JW
1276
1277 tmp = TREE_TYPE (sym->backend_decl);
1278 tmp = gfc_build_addr_expr (tmp, se.expr);
1279 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
8b704316 1280
6312ef45
JW
1281 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1282 gfc_finish_block (&se.post));
1283 }
1284
1285 /* Do a simple assignment. This is for scalar expressions, where we
1286 can simply use expression assignment. */
1287 else
1288 {
1289 gfc_expr *lhs;
1290
1291 lhs = gfc_lval_expr_from_sym (sym);
1292 tmp = gfc_trans_assignment (lhs, e, false, true);
1293 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1294 }
8b704316
PT
1295
1296 /* Set the stringlength from the vtable size. */
1297 if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
1298 {
1299 tree charlen;
1300 gfc_se se;
1301 gfc_init_se (&se, NULL);
1302 gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
1303 tmp = gfc_get_symbol_decl (e->symtree->n.sym);
1304 tmp = gfc_vtable_size_get (tmp);
1305 gfc_get_symbol_decl (sym);
1306 charlen = sym->ts.u.cl->backend_decl;
1307 gfc_add_modify (&se.pre, charlen,
1308 fold_convert (TREE_TYPE (charlen), tmp));
1309 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1310 gfc_finish_block (&se.post));
1311 }
6312ef45
JW
1312}
1313
1314
9abe5e56
DK
1315/* Translate a BLOCK construct. This is basically what we would do for a
1316 procedure body. */
1317
1318tree
1319gfc_trans_block_construct (gfc_code* code)
1320{
1321 gfc_namespace* ns;
1322 gfc_symbol* sym;
e5ca9693
DK
1323 gfc_wrapped_block block;
1324 tree exit_label;
1325 stmtblock_t body;
6312ef45 1326 gfc_association_list *ass;
9abe5e56 1327
03af1e4c 1328 ns = code->ext.block.ns;
9abe5e56
DK
1329 gcc_assert (ns);
1330 sym = ns->proc_name;
1331 gcc_assert (sym);
1332
e5ca9693 1333 /* Process local variables. */
9abe5e56
DK
1334 gcc_assert (!sym->tlink);
1335 sym->tlink = sym;
6312ef45 1336 gfc_process_block_locals (ns);
9abe5e56 1337
e5ca9693
DK
1338 /* Generate code including exit-label. */
1339 gfc_init_block (&body);
1340 exit_label = gfc_build_label_decl (NULL_TREE);
1341 code->exit_label = exit_label;
1342 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1343 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1344
1345 /* Finish everything. */
1346 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1347 gfc_trans_deferred_vars (sym, &block);
6312ef45
JW
1348 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1349 trans_associate_var (ass->st->n.sym, &block);
8b704316 1350
e5ca9693 1351 return gfc_finish_wrapped_block (&block);
9abe5e56
DK
1352}
1353
1354
54c2d931 1355/* Translate the simple DO construct. This is where the loop variable has
fbdad37d
PB
1356 integer type and step +-1. We can't use this in the general case
1357 because integer overflow and floating point errors could give incorrect
1358 results.
1359 We translate a do loop from:
1360
1361 DO dovar = from, to, step
1362 body
1363 END DO
1364
1365 to:
1366
1367 [Evaluate loop bounds and step]
1368 dovar = from;
1369 if ((step > 0) ? (dovar <= to) : (dovar => to))
1370 {
1371 for (;;)
1372 {
1373 body;
1374 cycle_label:
1375 cond = (dovar == to);
1376 dovar += step;
1377 if (cond) goto end_label;
1378 }
1379 }
1380 end_label:
1381
1382 This helps the optimizers by avoiding the extra induction variable
1383 used in the general case. */
1384
1385static tree
1386gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
bc51e726 1387 tree from, tree to, tree step, tree exit_cond)
fbdad37d
PB
1388{
1389 stmtblock_t body;
1390 tree type;
1391 tree cond;
1392 tree tmp;
33abc845 1393 tree saved_dovar = NULL;
fbdad37d
PB
1394 tree cycle_label;
1395 tree exit_label;
55bd9c35 1396 location_t loc;
8b704316 1397
fbdad37d
PB
1398 type = TREE_TYPE (dovar);
1399
55bd9c35
TB
1400 loc = code->ext.iterator->start->where.lb->location;
1401
fbdad37d 1402 /* Initialize the DO variable: dovar = from. */
8594f636
TB
1403 gfc_add_modify_loc (loc, pblock, dovar,
1404 fold_convert (TREE_TYPE(dovar), from));
8b704316 1405
33abc845
TB
1406 /* Save value for do-tinkering checking. */
1407 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1408 {
1409 saved_dovar = gfc_create_var (type, ".saved_dovar");
55bd9c35 1410 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
33abc845 1411 }
fbdad37d
PB
1412
1413 /* Cycle and exit statements are implemented with gotos. */
1414 cycle_label = gfc_build_label_decl (NULL_TREE);
1415 exit_label = gfc_build_label_decl (NULL_TREE);
1416
1417 /* Put the labels where they can be found later. See gfc_trans_do(). */
e5ca9693
DK
1418 code->cycle_label = cycle_label;
1419 code->exit_label = exit_label;
fbdad37d
PB
1420
1421 /* Loop body. */
1422 gfc_start_block (&body);
1423
1424 /* Main loop body. */
bc51e726 1425 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
fbdad37d
PB
1426 gfc_add_expr_to_block (&body, tmp);
1427
1428 /* Label for cycle statements (if needed). */
1429 if (TREE_USED (cycle_label))
1430 {
1431 tmp = build1_v (LABEL_EXPR, cycle_label);
1432 gfc_add_expr_to_block (&body, tmp);
1433 }
1434
33abc845
TB
1435 /* Check whether someone has modified the loop variable. */
1436 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1437 {
55bd9c35 1438 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
bc98ed60 1439 dovar, saved_dovar);
33abc845
TB
1440 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1441 "Loop variable has been modified");
1442 }
1443
bc51e726
JD
1444 /* Exit the loop if there is an I/O result condition or error. */
1445 if (exit_cond)
1446 {
1447 tmp = build1_v (GOTO_EXPR, exit_label);
55bd9c35 1448 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
bc98ed60 1449 exit_cond, tmp,
55bd9c35 1450 build_empty_stmt (loc));
bc51e726
JD
1451 gfc_add_expr_to_block (&body, tmp);
1452 }
1453
fbdad37d 1454 /* Evaluate the loop condition. */
55bd9c35 1455 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
bc98ed60 1456 to);
55bd9c35 1457 cond = gfc_evaluate_now_loc (loc, cond, &body);
fbdad37d
PB
1458
1459 /* Increment the loop variable. */
55bd9c35
TB
1460 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1461 gfc_add_modify_loc (loc, &body, dovar, tmp);
fbdad37d 1462
33abc845 1463 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
55bd9c35 1464 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
33abc845 1465
fbdad37d 1466 /* The loop exit. */
55bd9c35 1467 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
fbdad37d 1468 TREE_USED (exit_label) = 1;
55bd9c35
TB
1469 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1470 cond, tmp, build_empty_stmt (loc));
fbdad37d
PB
1471 gfc_add_expr_to_block (&body, tmp);
1472
1473 /* Finish the loop body. */
1474 tmp = gfc_finish_block (&body);
55bd9c35 1475 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
fbdad37d
PB
1476
1477 /* Only execute the loop if the number of iterations is positive. */
1478 if (tree_int_cst_sgn (step) > 0)
55bd9c35 1479 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
bc98ed60 1480 to);
fbdad37d 1481 else
55bd9c35 1482 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
bc98ed60 1483 to);
55bd9c35
TB
1484 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1485 build_empty_stmt (loc));
fbdad37d
PB
1486 gfc_add_expr_to_block (pblock, tmp);
1487
1488 /* Add the exit label. */
1489 tmp = build1_v (LABEL_EXPR, exit_label);
1490 gfc_add_expr_to_block (pblock, tmp);
1491
1492 return gfc_finish_block (pblock);
1493}
1494
6de9cd9a
DN
1495/* Translate the DO construct. This obviously is one of the most
1496 important ones to get right with any compiler, but especially
1497 so for Fortran.
1498
fbdad37d
PB
1499 We special case some loop forms as described in gfc_trans_simple_do.
1500 For other cases we implement them with a separate loop count,
1501 as described in the standard.
6de9cd9a
DN
1502
1503 We translate a do loop from:
1504
1505 DO dovar = from, to, step
1506 body
1507 END DO
1508
1509 to:
1510
fbdad37d 1511 [evaluate loop bounds and step]
5d148c08
FXC
1512 empty = (step > 0 ? to < from : to > from);
1513 countm1 = (to - from) / step;
fbdad37d 1514 dovar = from;
5d148c08 1515 if (empty) goto exit_label;
fbdad37d 1516 for (;;)
6de9cd9a
DN
1517 {
1518 body;
1519cycle_label:
fbdad37d 1520 dovar += step
8c01de7f 1521 countm1t = countm1;
76dac339 1522 countm1--;
8c01de7f 1523 if (countm1t == 0) goto exit_label;
6de9cd9a
DN
1524 }
1525exit_label:
1526
5d148c08
FXC
1527 countm1 is an unsigned integer. It is equal to the loop count minus one,
1528 because the loop count itself can overflow. */
6de9cd9a
DN
1529
1530tree
bc51e726 1531gfc_trans_do (gfc_code * code, tree exit_cond)
6de9cd9a
DN
1532{
1533 gfc_se se;
1534 tree dovar;
33abc845 1535 tree saved_dovar = NULL;
6de9cd9a
DN
1536 tree from;
1537 tree to;
1538 tree step;
5d148c08 1539 tree countm1;
6de9cd9a 1540 tree type;
5d148c08 1541 tree utype;
6de9cd9a
DN
1542 tree cond;
1543 tree cycle_label;
1544 tree exit_label;
1545 tree tmp;
1546 stmtblock_t block;
1547 stmtblock_t body;
55bd9c35 1548 location_t loc;
6de9cd9a
DN
1549
1550 gfc_start_block (&block);
1551
55bd9c35
TB
1552 loc = code->ext.iterator->start->where.lb->location;
1553
fbdad37d 1554 /* Evaluate all the expressions in the iterator. */
6de9cd9a
DN
1555 gfc_init_se (&se, NULL);
1556 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1557 gfc_add_block_to_block (&block, &se.pre);
1558 dovar = se.expr;
1559 type = TREE_TYPE (dovar);
1560
1561 gfc_init_se (&se, NULL);
8d5cfa27 1562 gfc_conv_expr_val (&se, code->ext.iterator->start);
6de9cd9a 1563 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 1564 from = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
1565
1566 gfc_init_se (&se, NULL);
8d5cfa27 1567 gfc_conv_expr_val (&se, code->ext.iterator->end);
6de9cd9a 1568 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 1569 to = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
1570
1571 gfc_init_se (&se, NULL);
8d5cfa27 1572 gfc_conv_expr_val (&se, code->ext.iterator->step);
6de9cd9a 1573 gfc_add_block_to_block (&block, &se.pre);
fbdad37d
PB
1574 step = gfc_evaluate_now (se.expr, &block);
1575
33abc845
TB
1576 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1577 {
bc98ed60 1578 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
e8160c9a 1579 build_zero_cst (type));
33abc845
TB
1580 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1581 "DO step value is zero");
1582 }
1583
fbdad37d
PB
1584 /* Special case simple loops. */
1585 if (TREE_CODE (type) == INTEGER_TYPE
1586 && (integer_onep (step)
1587 || tree_int_cst_equal (step, integer_minus_one_node)))
bc51e726 1588 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
c0b29099 1589
6de9cd9a 1590
8d5cfa27 1591 if (TREE_CODE (type) == INTEGER_TYPE)
c0b29099
JJ
1592 utype = unsigned_type_for (type);
1593 else
1594 utype = unsigned_type_for (gfc_array_index_type);
1595 countm1 = gfc_create_var (utype, "countm1");
5d148c08 1596
c0b29099
JJ
1597 /* Cycle and exit statements are implemented with gotos. */
1598 cycle_label = gfc_build_label_decl (NULL_TREE);
1599 exit_label = gfc_build_label_decl (NULL_TREE);
1600 TREE_USED (exit_label) = 1;
1601
e5ca9693
DK
1602 /* Put these labels where they can be found later. */
1603 code->cycle_label = cycle_label;
1604 code->exit_label = exit_label;
1605
c0b29099
JJ
1606 /* Initialize the DO variable: dovar = from. */
1607 gfc_add_modify (&block, dovar, from);
1608
33abc845
TB
1609 /* Save value for do-tinkering checking. */
1610 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1611 {
1612 saved_dovar = gfc_create_var (type, ".saved_dovar");
55bd9c35 1613 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
33abc845
TB
1614 }
1615
c0b29099
JJ
1616 /* Initialize loop count and jump to exit label if the loop is empty.
1617 This code is executed before we enter the loop body. We generate:
1618 if (step > 0)
1619 {
8146bb58
TK
1620 if (to < from)
1621 goto exit_label;
c5e7e996 1622 countm1 = (to - from) / step;
c0b29099
JJ
1623 }
1624 else
1625 {
8146bb58
TK
1626 if (to > from)
1627 goto exit_label;
c5e7e996 1628 countm1 = (from - to) / -step;
8146bb58 1629 }
c5e7e996 1630 */
8146bb58 1631
c0b29099
JJ
1632 if (TREE_CODE (type) == INTEGER_TYPE)
1633 {
c5e7e996 1634 tree pos, neg, tou, fromu, stepu, tmp2;
8146bb58 1635
c5e7e996
RB
1636 /* The distance from FROM to TO cannot always be represented in a signed
1637 type, thus use unsigned arithmetic, also to avoid any undefined
1638 overflow issues. */
1639 tou = fold_convert (utype, to);
1640 fromu = fold_convert (utype, from);
1641 stepu = fold_convert (utype, step);
5d148c08 1642
c5e7e996
RB
1643 /* For a positive step, when to < from, exit, otherwise compute
1644 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
55bd9c35 1645 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
c5e7e996
RB
1646 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1647 fold_build2_loc (loc, MINUS_EXPR, utype,
1648 tou, fromu),
1649 stepu);
55bd9c35
TB
1650 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1651 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1652 exit_label),
c5e7e996
RB
1653 fold_build2 (MODIFY_EXPR, void_type_node,
1654 countm1, tmp2));
1655
1656 /* For a negative step, when to > from, exit, otherwise compute
1657 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1658 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1659 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1660 fold_build2_loc (loc, MINUS_EXPR, utype,
1661 fromu, tou),
1662 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
55bd9c35
TB
1663 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1664 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1665 exit_label),
c5e7e996
RB
1666 fold_build2 (MODIFY_EXPR, void_type_node,
1667 countm1, tmp2));
8146bb58 1668
c5e7e996
RB
1669 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1670 build_int_cst (TREE_TYPE (step), 0));
1671 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
8146bb58 1672
c0b29099 1673 gfc_add_expr_to_block (&block, tmp);
8d5cfa27
SK
1674 }
1675 else
1676 {
c5e7e996
RB
1677 tree pos_step;
1678
8d5cfa27
SK
1679 /* TODO: We could use the same width as the real type.
1680 This would probably cause more problems that it solves
1681 when we implement "long double" types. */
c0b29099 1682
55bd9c35
TB
1683 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1684 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1685 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
c0b29099
JJ
1686 gfc_add_modify (&block, countm1, tmp);
1687
1688 /* We need a special check for empty loops:
1689 empty = (step > 0 ? to < from : to > from); */
c5e7e996
RB
1690 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1691 build_zero_cst (type));
55bd9c35
TB
1692 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1693 fold_build2_loc (loc, LT_EXPR,
bc98ed60 1694 boolean_type_node, to, from),
55bd9c35 1695 fold_build2_loc (loc, GT_EXPR,
bc98ed60 1696 boolean_type_node, to, from));
c0b29099 1697 /* If the loop is empty, go directly to the exit label. */
55bd9c35 1698 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
c0b29099 1699 build1_v (GOTO_EXPR, exit_label),
c2255bc4 1700 build_empty_stmt (input_location));
c0b29099 1701 gfc_add_expr_to_block (&block, tmp);
8d5cfa27 1702 }
5d148c08 1703
6de9cd9a
DN
1704 /* Loop body. */
1705 gfc_start_block (&body);
1706
6de9cd9a 1707 /* Main loop body. */
bc51e726 1708 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
6de9cd9a
DN
1709 gfc_add_expr_to_block (&body, tmp);
1710
1711 /* Label for cycle statements (if needed). */
1712 if (TREE_USED (cycle_label))
1713 {
1714 tmp = build1_v (LABEL_EXPR, cycle_label);
1715 gfc_add_expr_to_block (&body, tmp);
1716 }
1717
33abc845
TB
1718 /* Check whether someone has modified the loop variable. */
1719 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1720 {
55bd9c35 1721 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
bc98ed60 1722 saved_dovar);
33abc845
TB
1723 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1724 "Loop variable has been modified");
1725 }
1726
bc51e726
JD
1727 /* Exit the loop if there is an I/O result condition or error. */
1728 if (exit_cond)
1729 {
1730 tmp = build1_v (GOTO_EXPR, exit_label);
55bd9c35 1731 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
bc98ed60
TB
1732 exit_cond, tmp,
1733 build_empty_stmt (input_location));
bc51e726
JD
1734 gfc_add_expr_to_block (&body, tmp);
1735 }
1736
244974bd 1737 /* Increment the loop variable. */
55bd9c35
TB
1738 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1739 gfc_add_modify_loc (loc, &body, dovar, tmp);
244974bd 1740
33abc845 1741 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
55bd9c35 1742 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
33abc845 1743
8c01de7f
JJ
1744 /* Initialize countm1t. */
1745 tree countm1t = gfc_create_var (utype, "countm1t");
1746 gfc_add_modify_loc (loc, &body, countm1t, countm1);
5d148c08 1747
6de9cd9a 1748 /* Decrement the loop count. */
55bd9c35 1749 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
bc98ed60 1750 build_int_cst (utype, 1));
55bd9c35 1751 gfc_add_modify_loc (loc, &body, countm1, tmp);
6de9cd9a 1752
8c01de7f
JJ
1753 /* End with the loop condition. Loop until countm1t == 0. */
1754 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1755 build_int_cst (utype, 0));
1756 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1757 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1758 cond, tmp, build_empty_stmt (loc));
1759 gfc_add_expr_to_block (&body, tmp);
1760
6de9cd9a
DN
1761 /* End of loop body. */
1762 tmp = gfc_finish_block (&body);
1763
1764 /* The for loop itself. */
55bd9c35 1765 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
6de9cd9a
DN
1766 gfc_add_expr_to_block (&block, tmp);
1767
1768 /* Add the exit label. */
1769 tmp = build1_v (LABEL_EXPR, exit_label);
1770 gfc_add_expr_to_block (&block, tmp);
1771
1772 return gfc_finish_block (&block);
1773}
1774
1775
1776/* Translate the DO WHILE construct.
1777
1778 We translate
1779
1780 DO WHILE (cond)
1781 body
1782 END DO
1783
1784 to:
1785
1786 for ( ; ; )
1787 {
1788 pre_cond;
1789 if (! cond) goto exit_label;
1790 body;
1791cycle_label:
1792 }
1793exit_label:
1794
1795 Because the evaluation of the exit condition `cond' may have side
1796 effects, we can't do much for empty loop bodies. The backend optimizers
1797 should be smart enough to eliminate any dead loops. */
1798
1799tree
1800gfc_trans_do_while (gfc_code * code)
1801{
1802 gfc_se cond;
1803 tree tmp;
1804 tree cycle_label;
1805 tree exit_label;
1806 stmtblock_t block;
1807
1808 /* Everything we build here is part of the loop body. */
1809 gfc_start_block (&block);
1810
1811 /* Cycle and exit statements are implemented with gotos. */
1812 cycle_label = gfc_build_label_decl (NULL_TREE);
1813 exit_label = gfc_build_label_decl (NULL_TREE);
1814
1815 /* Put the labels where they can be found later. See gfc_trans_do(). */
e5ca9693
DK
1816 code->cycle_label = cycle_label;
1817 code->exit_label = exit_label;
6de9cd9a
DN
1818
1819 /* Create a GIMPLE version of the exit condition. */
1820 gfc_init_se (&cond, NULL);
a513927a 1821 gfc_conv_expr_val (&cond, code->expr1);
6de9cd9a 1822 gfc_add_block_to_block (&block, &cond.pre);
55bd9c35 1823 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1d636855 1824 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
6de9cd9a
DN
1825
1826 /* Build "IF (! cond) GOTO exit_label". */
1827 tmp = build1_v (GOTO_EXPR, exit_label);
1828 TREE_USED (exit_label) = 1;
55bd9c35
TB
1829 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1830 void_type_node, cond.expr, tmp,
1831 build_empty_stmt (code->expr1->where.lb->location));
6de9cd9a
DN
1832 gfc_add_expr_to_block (&block, tmp);
1833
1834 /* The main body of the loop. */
1835 tmp = gfc_trans_code (code->block->next);
1836 gfc_add_expr_to_block (&block, tmp);
1837
1838 /* Label for cycle statements (if needed). */
1839 if (TREE_USED (cycle_label))
1840 {
1841 tmp = build1_v (LABEL_EXPR, cycle_label);
1842 gfc_add_expr_to_block (&block, tmp);
1843 }
1844
1845 /* End of loop body. */
1846 tmp = gfc_finish_block (&block);
1847
1848 gfc_init_block (&block);
1849 /* Build the loop. */
55bd9c35
TB
1850 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1851 void_type_node, tmp);
6de9cd9a
DN
1852 gfc_add_expr_to_block (&block, tmp);
1853
1854 /* Add the exit label. */
1855 tmp = build1_v (LABEL_EXPR, exit_label);
1856 gfc_add_expr_to_block (&block, tmp);
1857
1858 return gfc_finish_block (&block);
1859}
1860
1861
1862/* Translate the SELECT CASE construct for INTEGER case expressions,
1863 without killing all potential optimizations. The problem is that
1864 Fortran allows unbounded cases, but the back-end does not, so we
1865 need to intercept those before we enter the equivalent SWITCH_EXPR
1866 we can build.
1867
1868 For example, we translate this,
1869
1870 SELECT CASE (expr)
1871 CASE (:100,101,105:115)
1872 block_1
1873 CASE (190:199,200:)
1874 block_2
1875 CASE (300)
1876 block_3
1877 CASE DEFAULT
1878 block_4
1879 END SELECT
1880
1881 to the GENERIC equivalent,
1882
1883 switch (expr)
1884 {
1885 case (minimum value for typeof(expr) ... 100:
1886 case 101:
1887 case 105 ... 114:
1888 block1:
1889 goto end_label;
1890
1891 case 200 ... (maximum value for typeof(expr):
1892 case 190 ... 199:
1893 block2;
1894 goto end_label;
1895
1896 case 300:
1897 block_3;
1898 goto end_label;
1899
1900 default:
1901 block_4;
1902 goto end_label;
1903 }
1904
1905 end_label: */
1906
1907static tree
1908gfc_trans_integer_select (gfc_code * code)
1909{
1910 gfc_code *c;
1911 gfc_case *cp;
1912 tree end_label;
1913 tree tmp;
1914 gfc_se se;
1915 stmtblock_t block;
1916 stmtblock_t body;
1917
1918 gfc_start_block (&block);
1919
1920 /* Calculate the switch expression. */
1921 gfc_init_se (&se, NULL);
a513927a 1922 gfc_conv_expr_val (&se, code->expr1);
6de9cd9a
DN
1923 gfc_add_block_to_block (&block, &se.pre);
1924
1925 end_label = gfc_build_label_decl (NULL_TREE);
1926
1927 gfc_init_block (&body);
1928
1929 for (c = code->block; c; c = c->block)
1930 {
29a63d67 1931 for (cp = c->ext.block.case_list; cp; cp = cp->next)
6de9cd9a
DN
1932 {
1933 tree low, high;
1934 tree label;
1935
1936 /* Assume it's the default case. */
1937 low = high = NULL_TREE;
1938
1939 if (cp->low)
1940 {
20585ad6
BM
1941 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1942 cp->low->ts.kind);
6de9cd9a
DN
1943
1944 /* If there's only a lower bound, set the high bound to the
1945 maximum value of the case expression. */
1946 if (!cp->high)
1947 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1948 }
1949
1950 if (cp->high)
1951 {
1952 /* Three cases are possible here:
1953
1954 1) There is no lower bound, e.g. CASE (:N).
1955 2) There is a lower bound .NE. high bound, that is
1956 a case range, e.g. CASE (N:M) where M>N (we make
1957 sure that M>N during type resolution).
1958 3) There is a lower bound, and it has the same value
1959 as the high bound, e.g. CASE (N:N). This is our
1960 internal representation of CASE(N).
1961
1962 In the first and second case, we need to set a value for
e2ae1407 1963 high. In the third case, we don't because the GCC middle
6de9cd9a
DN
1964 end represents a single case value by just letting high be
1965 a NULL_TREE. We can't do that because we need to be able
1966 to represent unbounded cases. */
1967
1968 if (!cp->low
1969 || (cp->low
1970 && mpz_cmp (cp->low->value.integer,
1971 cp->high->value.integer) != 0))
20585ad6
BM
1972 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1973 cp->high->ts.kind);
6de9cd9a
DN
1974
1975 /* Unbounded case. */
1976 if (!cp->low)
1977 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1978 }
1979
1980 /* Build a label. */
c006df4e 1981 label = gfc_build_label_decl (NULL_TREE);
6de9cd9a
DN
1982
1983 /* Add this case label.
1984 Add parameter 'label', make it match GCC backend. */
3d528853 1985 tmp = build_case_label (low, high, label);
6de9cd9a
DN
1986 gfc_add_expr_to_block (&body, tmp);
1987 }
1988
1989 /* Add the statements for this case. */
1990 tmp = gfc_trans_code (c->next);
1991 gfc_add_expr_to_block (&body, tmp);
1992
1993 /* Break to the end of the construct. */
1994 tmp = build1_v (GOTO_EXPR, end_label);
1995 gfc_add_expr_to_block (&body, tmp);
1996 }
1997
1998 tmp = gfc_finish_block (&body);
0cd2402d
SB
1999 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2000 se.expr, tmp, NULL_TREE);
6de9cd9a
DN
2001 gfc_add_expr_to_block (&block, tmp);
2002
2003 tmp = build1_v (LABEL_EXPR, end_label);
2004 gfc_add_expr_to_block (&block, tmp);
2005
2006 return gfc_finish_block (&block);
2007}
2008
2009
2010/* Translate the SELECT CASE construct for LOGICAL case expressions.
2011
2012 There are only two cases possible here, even though the standard
2013 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2014 .FALSE., and DEFAULT.
2015
2016 We never generate more than two blocks here. Instead, we always
2017 try to eliminate the DEFAULT case. This way, we can translate this
2018 kind of SELECT construct to a simple
2019
2020 if {} else {};
2021
2022 expression in GENERIC. */
2023
2024static tree
2025gfc_trans_logical_select (gfc_code * code)
2026{
2027 gfc_code *c;
2028 gfc_code *t, *f, *d;
2029 gfc_case *cp;
2030 gfc_se se;
2031 stmtblock_t block;
2032
2033 /* Assume we don't have any cases at all. */
2034 t = f = d = NULL;
2035
2036 /* Now see which ones we actually do have. We can have at most two
2037 cases in a single case list: one for .TRUE. and one for .FALSE.
2038 The default case is always separate. If the cases for .TRUE. and
2039 .FALSE. are in the same case list, the block for that case list
2040 always executed, and we don't generate code a COND_EXPR. */
2041 for (c = code->block; c; c = c->block)
2042 {
29a63d67 2043 for (cp = c->ext.block.case_list; cp; cp = cp->next)
6de9cd9a
DN
2044 {
2045 if (cp->low)
2046 {
2047 if (cp->low->value.logical == 0) /* .FALSE. */
2048 f = c;
2049 else /* if (cp->value.logical != 0), thus .TRUE. */
2050 t = c;
2051 }
2052 else
2053 d = c;
2054 }
2055 }
2056
2057 /* Start a new block. */
2058 gfc_start_block (&block);
2059
2060 /* Calculate the switch expression. We always need to do this
2061 because it may have side effects. */
2062 gfc_init_se (&se, NULL);
a513927a 2063 gfc_conv_expr_val (&se, code->expr1);
6de9cd9a
DN
2064 gfc_add_block_to_block (&block, &se.pre);
2065
2066 if (t == f && t != NULL)
2067 {
2068 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2069 translate the code for these cases, append it to the current
2070 block. */
2071 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2072 }
2073 else
2074 {
61ead135 2075 tree true_tree, false_tree, stmt;
6de9cd9a 2076
c2255bc4
AH
2077 true_tree = build_empty_stmt (input_location);
2078 false_tree = build_empty_stmt (input_location);
6de9cd9a
DN
2079
2080 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2081 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2082 make the missing case the default case. */
2083 if (t != NULL && f != NULL)
2084 d = NULL;
2085 else if (d != NULL)
2086 {
2087 if (t == NULL)
2088 t = d;
2089 else
2090 f = d;
2091 }
2092
2093 /* Translate the code for each of these blocks, and append it to
2094 the current block. */
2095 if (t != NULL)
2096 true_tree = gfc_trans_code (t->next);
2097
2098 if (f != NULL)
2099 false_tree = gfc_trans_code (f->next);
2100
bc98ed60
TB
2101 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2102 se.expr, true_tree, false_tree);
61ead135 2103 gfc_add_expr_to_block (&block, stmt);
6de9cd9a
DN
2104 }
2105
2106 return gfc_finish_block (&block);
2107}
2108
2109
d2886bc7
JJ
2110/* The jump table types are stored in static variables to avoid
2111 constructing them from scratch every single time. */
2112static GTY(()) tree select_struct[2];
2113
6de9cd9a
DN
2114/* Translate the SELECT CASE construct for CHARACTER case expressions.
2115 Instead of generating compares and jumps, it is far simpler to
2116 generate a data structure describing the cases in order and call a
2117 library subroutine that locates the right case.
2118 This is particularly true because this is the only case where we
2119 might have to dispose of a temporary.
2120 The library subroutine returns a pointer to jump to or NULL if no
2121 branches are to be taken. */
2122
2123static tree
2124gfc_trans_character_select (gfc_code *code)
2125{
8748ad99 2126 tree init, end_label, tmp, type, case_num, label, fndecl;
6de9cd9a
DN
2127 stmtblock_t block, body;
2128 gfc_case *cp, *d;
2129 gfc_code *c;
d2886bc7 2130 gfc_se se, expr1se;
d393bbd7 2131 int n, k;
9771b263 2132 vec<constructor_elt, va_gc> *inits = NULL;
d393bbd7 2133
d2886bc7
JJ
2134 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2135
d393bbd7
FXC
2136 /* The jump table types are stored in static variables to avoid
2137 constructing them from scratch every single time. */
d393bbd7
FXC
2138 static tree ss_string1[2], ss_string1_len[2];
2139 static tree ss_string2[2], ss_string2_len[2];
2140 static tree ss_target[2];
2141
29a63d67 2142 cp = code->block->ext.block.case_list;
d2886bc7
JJ
2143 while (cp->left != NULL)
2144 cp = cp->left;
2145
2146 /* Generate the body */
2147 gfc_start_block (&block);
2148 gfc_init_se (&expr1se, NULL);
2149 gfc_conv_expr_reference (&expr1se, code->expr1);
2150
2151 gfc_add_block_to_block (&block, &expr1se.pre);
2152
2153 end_label = gfc_build_label_decl (NULL_TREE);
2154
2155 gfc_init_block (&body);
2156
2157 /* Attempt to optimize length 1 selects. */
86e033e2 2158 if (integer_onep (expr1se.string_length))
d2886bc7
JJ
2159 {
2160 for (d = cp; d; d = d->right)
2161 {
2162 int i;
2163 if (d->low)
2164 {
2165 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2166 && d->low->ts.type == BT_CHARACTER);
2167 if (d->low->value.character.length > 1)
2168 {
2169 for (i = 1; i < d->low->value.character.length; i++)
2170 if (d->low->value.character.string[i] != ' ')
2171 break;
2172 if (i != d->low->value.character.length)
2173 {
2174 if (optimize && d->high && i == 1)
2175 {
2176 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2177 && d->high->ts.type == BT_CHARACTER);
2178 if (d->high->value.character.length > 1
2179 && (d->low->value.character.string[0]
2180 == d->high->value.character.string[0])
2181 && d->high->value.character.string[1] != ' '
2182 && ((d->low->value.character.string[1] < ' ')
2183 == (d->high->value.character.string[1]
2184 < ' ')))
2185 continue;
2186 }
2187 break;
2188 }
2189 }
2190 }
2191 if (d->high)
2192 {
2193 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2194 && d->high->ts.type == BT_CHARACTER);
2195 if (d->high->value.character.length > 1)
2196 {
2197 for (i = 1; i < d->high->value.character.length; i++)
2198 if (d->high->value.character.string[i] != ' ')
2199 break;
2200 if (i != d->high->value.character.length)
2201 break;
2202 }
2203 }
2204 }
2205 if (d == NULL)
2206 {
2207 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2208
2209 for (c = code->block; c; c = c->block)
2210 {
29a63d67 2211 for (cp = c->ext.block.case_list; cp; cp = cp->next)
d2886bc7
JJ
2212 {
2213 tree low, high;
2214 tree label;
2215 gfc_char_t r;
2216
2217 /* Assume it's the default case. */
2218 low = high = NULL_TREE;
2219
2220 if (cp->low)
2221 {
2222 /* CASE ('ab') or CASE ('ab':'az') will never match
2223 any length 1 character. */
2224 if (cp->low->value.character.length > 1
2225 && cp->low->value.character.string[1] != ' ')
2226 continue;
2227
2228 if (cp->low->value.character.length > 0)
2229 r = cp->low->value.character.string[0];
2230 else
2231 r = ' ';
2232 low = build_int_cst (ctype, r);
2233
2234 /* If there's only a lower bound, set the high bound
2235 to the maximum value of the case expression. */
2236 if (!cp->high)
2237 high = TYPE_MAX_VALUE (ctype);
2238 }
2239
2240 if (cp->high)
2241 {
2242 if (!cp->low
2243 || (cp->low->value.character.string[0]
2244 != cp->high->value.character.string[0]))
2245 {
2246 if (cp->high->value.character.length > 0)
2247 r = cp->high->value.character.string[0];
2248 else
2249 r = ' ';
2250 high = build_int_cst (ctype, r);
2251 }
2252
2253 /* Unbounded case. */
2254 if (!cp->low)
2255 low = TYPE_MIN_VALUE (ctype);
2256 }
2257
2258 /* Build a label. */
2259 label = gfc_build_label_decl (NULL_TREE);
2260
2261 /* Add this case label.
2262 Add parameter 'label', make it match GCC backend. */
3d528853 2263 tmp = build_case_label (low, high, label);
d2886bc7
JJ
2264 gfc_add_expr_to_block (&body, tmp);
2265 }
2266
2267 /* Add the statements for this case. */
2268 tmp = gfc_trans_code (c->next);
2269 gfc_add_expr_to_block (&body, tmp);
2270
2271 /* Break to the end of the construct. */
2272 tmp = build1_v (GOTO_EXPR, end_label);
2273 gfc_add_expr_to_block (&body, tmp);
2274 }
2275
2276 tmp = gfc_string_to_single_character (expr1se.string_length,
2277 expr1se.expr,
2278 code->expr1->ts.kind);
2279 case_num = gfc_create_var (ctype, "case_num");
2280 gfc_add_modify (&block, case_num, tmp);
2281
2282 gfc_add_block_to_block (&block, &expr1se.post);
2283
2284 tmp = gfc_finish_block (&body);
0cd2402d
SB
2285 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2286 case_num, tmp, NULL_TREE);
d2886bc7
JJ
2287 gfc_add_expr_to_block (&block, tmp);
2288
2289 tmp = build1_v (LABEL_EXPR, end_label);
2290 gfc_add_expr_to_block (&block, tmp);
2291
2292 return gfc_finish_block (&block);
2293 }
2294 }
6de9cd9a 2295
a513927a 2296 if (code->expr1->ts.kind == 1)
d393bbd7 2297 k = 0;
a513927a 2298 else if (code->expr1->ts.kind == 4)
d393bbd7
FXC
2299 k = 1;
2300 else
2301 gcc_unreachable ();
6de9cd9a 2302
d393bbd7 2303 if (select_struct[k] == NULL)
6de9cd9a 2304 {
dfd6ece2 2305 tree *chain = NULL;
d393bbd7 2306 select_struct[k] = make_node (RECORD_TYPE);
e2cad04b 2307
a513927a 2308 if (code->expr1->ts.kind == 1)
d393bbd7 2309 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
a513927a 2310 else if (code->expr1->ts.kind == 4)
d393bbd7
FXC
2311 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2312 else
2313 gcc_unreachable ();
6de9cd9a
DN
2314
2315#undef ADD_FIELD
35151cd5
MM
2316#define ADD_FIELD(NAME, TYPE) \
2317 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2318 get_identifier (stringize(NAME)), \
2319 TYPE, \
2320 &chain)
6de9cd9a 2321
d393bbd7
FXC
2322 ADD_FIELD (string1, pchartype);
2323 ADD_FIELD (string1_len, gfc_charlen_type_node);
6de9cd9a 2324
d393bbd7
FXC
2325 ADD_FIELD (string2, pchartype);
2326 ADD_FIELD (string2_len, gfc_charlen_type_node);
6de9cd9a 2327
dd52ecb0 2328 ADD_FIELD (target, integer_type_node);
6de9cd9a
DN
2329#undef ADD_FIELD
2330
d393bbd7 2331 gfc_finish_type (select_struct[k]);
6de9cd9a
DN
2332 }
2333
6de9cd9a
DN
2334 n = 0;
2335 for (d = cp; d; d = d->right)
2336 d->n = n++;
2337
6de9cd9a
DN
2338 for (c = code->block; c; c = c->block)
2339 {
29a63d67 2340 for (d = c->ext.block.case_list; d; d = d->next)
6de9cd9a 2341 {
2b8327ce 2342 label = gfc_build_label_decl (NULL_TREE);
3d528853
NF
2343 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2344 ? NULL
2345 : build_int_cst (integer_type_node, d->n),
2346 NULL, label);
6de9cd9a
DN
2347 gfc_add_expr_to_block (&body, tmp);
2348 }
2349
2350 tmp = gfc_trans_code (c->next);
2351 gfc_add_expr_to_block (&body, tmp);
2352
923ab88c 2353 tmp = build1_v (GOTO_EXPR, end_label);
6de9cd9a
DN
2354 gfc_add_expr_to_block (&body, tmp);
2355 }
2356
2357 /* Generate the structure describing the branches */
d2886bc7 2358 for (d = cp; d; d = d->right)
6de9cd9a 2359 {
9771b263 2360 vec<constructor_elt, va_gc> *node = NULL;
6de9cd9a
DN
2361
2362 gfc_init_se (&se, NULL);
2363
2364 if (d->low == NULL)
2365 {
8748ad99
NF
2366 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2367 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
6de9cd9a
DN
2368 }
2369 else
2370 {
2371 gfc_conv_expr_reference (&se, d->low);
2372
8748ad99
NF
2373 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2374 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
6de9cd9a
DN
2375 }
2376
2377 if (d->high == NULL)
2378 {
8748ad99
NF
2379 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2380 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
6de9cd9a
DN
2381 }
2382 else
2383 {
2384 gfc_init_se (&se, NULL);
2385 gfc_conv_expr_reference (&se, d->high);
2386
8748ad99
NF
2387 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2388 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
6de9cd9a
DN
2389 }
2390
8748ad99
NF
2391 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2392 build_int_cst (integer_type_node, d->n));
6de9cd9a 2393
8748ad99
NF
2394 tmp = build_constructor (select_struct[k], node);
2395 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
6de9cd9a
DN
2396 }
2397
d393bbd7 2398 type = build_array_type (select_struct[k],
df09d1d5 2399 build_index_type (size_int (n-1)));
6de9cd9a 2400
8748ad99 2401 init = build_constructor (type, inits);
6de9cd9a 2402 TREE_CONSTANT (init) = 1;
6de9cd9a
DN
2403 TREE_STATIC (init) = 1;
2404 /* Create a static variable to hold the jump table. */
2405 tmp = gfc_create_var (type, "jumptable");
2406 TREE_CONSTANT (tmp) = 1;
6de9cd9a 2407 TREE_STATIC (tmp) = 1;
0f0707d1 2408 TREE_READONLY (tmp) = 1;
6de9cd9a
DN
2409 DECL_INITIAL (tmp) = init;
2410 init = tmp;
2411
5039610b 2412 /* Build the library call */
6de9cd9a 2413 init = gfc_build_addr_expr (pvoid_type_node, init);
6de9cd9a 2414
a513927a 2415 if (code->expr1->ts.kind == 1)
d393bbd7 2416 fndecl = gfor_fndecl_select_string;
a513927a 2417 else if (code->expr1->ts.kind == 4)
d393bbd7
FXC
2418 fndecl = gfor_fndecl_select_string_char4;
2419 else
2420 gcc_unreachable ();
2421
db3927fb 2422 tmp = build_call_expr_loc (input_location,
df09d1d5
RG
2423 fndecl, 4, init,
2424 build_int_cst (gfc_charlen_type_node, n),
d2886bc7 2425 expr1se.expr, expr1se.string_length);
dd52ecb0 2426 case_num = gfc_create_var (integer_type_node, "case_num");
726a989a 2427 gfc_add_modify (&block, case_num, tmp);
dc6c7714 2428
d2886bc7 2429 gfc_add_block_to_block (&block, &expr1se.post);
dc6c7714 2430
6de9cd9a 2431 tmp = gfc_finish_block (&body);
0cd2402d
SB
2432 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2433 case_num, tmp, NULL_TREE);
6de9cd9a 2434 gfc_add_expr_to_block (&block, tmp);
2b8327ce 2435
923ab88c 2436 tmp = build1_v (LABEL_EXPR, end_label);
6de9cd9a
DN
2437 gfc_add_expr_to_block (&block, tmp);
2438
6de9cd9a
DN
2439 return gfc_finish_block (&block);
2440}
2441
2442
2443/* Translate the three variants of the SELECT CASE construct.
2444
2445 SELECT CASEs with INTEGER case expressions can be translated to an
2446 equivalent GENERIC switch statement, and for LOGICAL case
2447 expressions we build one or two if-else compares.
2448
2449 SELECT CASEs with CHARACTER case expressions are a whole different
2450 story, because they don't exist in GENERIC. So we sort them and
2451 do a binary search at runtime.
2452
2453 Fortran has no BREAK statement, and it does not allow jumps from
2454 one case block to another. That makes things a lot easier for
2455 the optimizers. */
2456
2457tree
2458gfc_trans_select (gfc_code * code)
2459{
e5ca9693
DK
2460 stmtblock_t block;
2461 tree body;
2462 tree exit_label;
2463
a513927a 2464 gcc_assert (code && code->expr1);
e5ca9693
DK
2465 gfc_init_block (&block);
2466
2467 /* Build the exit label and hang it in. */
2468 exit_label = gfc_build_label_decl (NULL_TREE);
2469 code->exit_label = exit_label;
6de9cd9a
DN
2470
2471 /* Empty SELECT constructs are legal. */
2472 if (code->block == NULL)
e5ca9693 2473 body = build_empty_stmt (input_location);
6de9cd9a
DN
2474
2475 /* Select the correct translation function. */
e5ca9693
DK
2476 else
2477 switch (code->expr1->ts.type)
2478 {
2479 case BT_LOGICAL:
2480 body = gfc_trans_logical_select (code);
2481 break;
2482
2483 case BT_INTEGER:
2484 body = gfc_trans_integer_select (code);
2485 break;
2486
2487 case BT_CHARACTER:
2488 body = gfc_trans_character_select (code);
2489 break;
2490
2491 default:
2492 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2493 /* Not reached */
2494 }
2495
2496 /* Build everything together. */
2497 gfc_add_expr_to_block (&block, body);
2498 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2499
2500 return gfc_finish_block (&block);
6de9cd9a
DN
2501}
2502
2503
640670c7
PT
2504/* Traversal function to substitute a replacement symtree if the symbol
2505 in the expression is the same as that passed. f == 2 signals that
2506 that variable itself is not to be checked - only the references.
2507 This group of functions is used when the variable expression in a
2508 FORALL assignment has internal references. For example:
2509 FORALL (i = 1:4) p(p(i)) = i
2510 The only recourse here is to store a copy of 'p' for the index
2511 expression. */
2512
2513static gfc_symtree *new_symtree;
2514static gfc_symtree *old_symtree;
2515
2516static bool
2517forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2518{
908a2235
PT
2519 if (expr->expr_type != EXPR_VARIABLE)
2520 return false;
640670c7
PT
2521
2522 if (*f == 2)
2523 *f = 1;
2524 else if (expr->symtree->n.sym == sym)
2525 expr->symtree = new_symtree;
2526
2527 return false;
2528}
2529
2530static void
2531forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2532{
2533 gfc_traverse_expr (e, sym, forall_replace, f);
2534}
2535
2536static bool
2537forall_restore (gfc_expr *expr,
2538 gfc_symbol *sym ATTRIBUTE_UNUSED,
2539 int *f ATTRIBUTE_UNUSED)
2540{
908a2235
PT
2541 if (expr->expr_type != EXPR_VARIABLE)
2542 return false;
640670c7
PT
2543
2544 if (expr->symtree == new_symtree)
2545 expr->symtree = old_symtree;
2546
2547 return false;
2548}
2549
2550static void
2551forall_restore_symtree (gfc_expr *e)
2552{
2553 gfc_traverse_expr (e, NULL, forall_restore, 0);
2554}
2555
2556static void
2557forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2558{
2559 gfc_se tse;
2560 gfc_se rse;
2561 gfc_expr *e;
2562 gfc_symbol *new_sym;
2563 gfc_symbol *old_sym;
2564 gfc_symtree *root;
2565 tree tmp;
2566
2567 /* Build a copy of the lvalue. */
a513927a 2568 old_symtree = c->expr1->symtree;
640670c7
PT
2569 old_sym = old_symtree->n.sym;
2570 e = gfc_lval_expr_from_sym (old_sym);
2571 if (old_sym->attr.dimension)
2572 {
2573 gfc_init_se (&tse, NULL);
430f2d1f 2574 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
640670c7
PT
2575 gfc_add_block_to_block (pre, &tse.pre);
2576 gfc_add_block_to_block (post, &tse.post);
db3927fb 2577 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
640670c7
PT
2578
2579 if (e->ts.type != BT_CHARACTER)
2580 {
2581 /* Use the variable offset for the temporary. */
568e8e1e
PT
2582 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2583 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
640670c7
PT
2584 }
2585 }
2586 else
2587 {
2588 gfc_init_se (&tse, NULL);
2589 gfc_init_se (&rse, NULL);
2590 gfc_conv_expr (&rse, e);
2591 if (e->ts.type == BT_CHARACTER)
2592 {
2593 tse.string_length = rse.string_length;
2594 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2595 tse.string_length);
2596 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2597 rse.string_length);
2598 gfc_add_block_to_block (pre, &tse.pre);
2599 gfc_add_block_to_block (post, &tse.post);
2600 }
2601 else
2602 {
2603 tmp = gfc_typenode_for_spec (&e->ts);
2604 tse.expr = gfc_create_var (tmp, "temp");
2605 }
2606
2607 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2b56d6a4 2608 e->expr_type == EXPR_VARIABLE, true);
640670c7
PT
2609 gfc_add_expr_to_block (pre, tmp);
2610 }
2611 gfc_free_expr (e);
2612
2613 /* Create a new symbol to represent the lvalue. */
2614 new_sym = gfc_new_symbol (old_sym->name, NULL);
2615 new_sym->ts = old_sym->ts;
2616 new_sym->attr.referenced = 1;
59e36b72 2617 new_sym->attr.temporary = 1;
640670c7
PT
2618 new_sym->attr.dimension = old_sym->attr.dimension;
2619 new_sym->attr.flavor = old_sym->attr.flavor;
2620
2621 /* Use the temporary as the backend_decl. */
2622 new_sym->backend_decl = tse.expr;
2623
2624 /* Create a fake symtree for it. */
2625 root = NULL;
2626 new_symtree = gfc_new_symtree (&root, old_sym->name);
2627 new_symtree->n.sym = new_sym;
2628 gcc_assert (new_symtree == root);
2629
2630 /* Go through the expression reference replacing the old_symtree
2631 with the new. */
a513927a 2632 forall_replace_symtree (c->expr1, old_sym, 2);
640670c7
PT
2633
2634 /* Now we have made this temporary, we might as well use it for
2635 the right hand side. */
2636 forall_replace_symtree (c->expr2, old_sym, 1);
2637}
2638
2639
2640/* Handles dependencies in forall assignments. */
2641static int
2642check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2643{
2644 gfc_ref *lref;
2645 gfc_ref *rref;
2646 int need_temp;
2647 gfc_symbol *lsym;
2648
a513927a
SK
2649 lsym = c->expr1->symtree->n.sym;
2650 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
640670c7
PT
2651
2652 /* Now check for dependencies within the 'variable'
2653 expression itself. These are treated by making a complete
2654 copy of variable and changing all the references to it
2655 point to the copy instead. Note that the shallow copy of
2656 the variable will not suffice for derived types with
2657 pointer components. We therefore leave these to their
2658 own devices. */
2659 if (lsym->ts.type == BT_DERIVED
bc21d315 2660 && lsym->ts.u.derived->attr.pointer_comp)
640670c7
PT
2661 return need_temp;
2662
2663 new_symtree = NULL;
524af0d6 2664 if (find_forall_index (c->expr1, lsym, 2))
640670c7
PT
2665 {
2666 forall_make_variable_temp (c, pre, post);
2667 need_temp = 0;
2668 }
2669
2670 /* Substrings with dependencies are treated in the same
2671 way. */
a513927a
SK
2672 if (c->expr1->ts.type == BT_CHARACTER
2673 && c->expr1->ref
640670c7
PT
2674 && c->expr2->expr_type == EXPR_VARIABLE
2675 && lsym == c->expr2->symtree->n.sym)
2676 {
a513927a 2677 for (lref = c->expr1->ref; lref; lref = lref->next)
640670c7
PT
2678 if (lref->type == REF_SUBSTRING)
2679 break;
2680 for (rref = c->expr2->ref; rref; rref = rref->next)
2681 if (rref->type == REF_SUBSTRING)
2682 break;
2683
2684 if (rref && lref
2685 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2686 {
2687 forall_make_variable_temp (c, pre, post);
2688 need_temp = 0;
2689 }
2690 }
2691 return need_temp;
2692}
2693
2694
2695static void
2696cleanup_forall_symtrees (gfc_code *c)
2697{
a513927a 2698 forall_restore_symtree (c->expr1);
640670c7 2699 forall_restore_symtree (c->expr2);
cede9502
JM
2700 free (new_symtree->n.sym);
2701 free (new_symtree);
640670c7
PT
2702}
2703
2704
bfcabc6c
RS
2705/* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2706 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2707 indicates whether we should generate code to test the FORALLs mask
2708 array. OUTER is the loop header to be used for initializing mask
2709 indices.
2710
2711 The generated loop format is:
6de9cd9a
DN
2712 count = (end - start + step) / step
2713 loopvar = start
2714 while (1)
2715 {
2716 if (count <=0 )
2717 goto end_of_loop
2718 <body>
2719 loopvar += step
2720 count --
2721 }
2722 end_of_loop: */
2723
2724static tree
bfcabc6c
RS
2725gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2726 int mask_flag, stmtblock_t *outer)
6de9cd9a 2727{
bfcabc6c 2728 int n, nvar;
6de9cd9a
DN
2729 tree tmp;
2730 tree cond;
2731 stmtblock_t block;
2732 tree exit_label;
2733 tree count;
fcf3be37 2734 tree var, start, end, step;
6de9cd9a
DN
2735 iter_info *iter;
2736
bfcabc6c
RS
2737 /* Initialize the mask index outside the FORALL nest. */
2738 if (mask_flag && forall_tmp->mask)
726a989a 2739 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
bfcabc6c 2740
6de9cd9a 2741 iter = forall_tmp->this_loop;
bfcabc6c 2742 nvar = forall_tmp->nvar;
6de9cd9a
DN
2743 for (n = 0; n < nvar; n++)
2744 {
2745 var = iter->var;
2746 start = iter->start;
2747 end = iter->end;
2748 step = iter->step;
2749
2750 exit_label = gfc_build_label_decl (NULL_TREE);
2751 TREE_USED (exit_label) = 1;
2752
2753 /* The loop counter. */
2754 count = gfc_create_var (TREE_TYPE (var), "count");
2755
2756 /* The body of the loop. */
2757 gfc_init_block (&block);
2758
2759 /* The exit condition. */
bc98ed60
TB
2760 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2761 count, build_int_cst (TREE_TYPE (count), 0));
6de9cd9a 2762 tmp = build1_v (GOTO_EXPR, exit_label);
bc98ed60
TB
2763 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2764 cond, tmp, build_empty_stmt (input_location));
6de9cd9a
DN
2765 gfc_add_expr_to_block (&block, tmp);
2766
2767 /* The main loop body. */
2768 gfc_add_expr_to_block (&block, body);
2769
2770 /* Increment the loop variable. */
bc98ed60
TB
2771 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2772 step);
726a989a 2773 gfc_add_modify (&block, var, tmp);
6de9cd9a 2774
a8e12e4d
TS
2775 /* Advance to the next mask element. Only do this for the
2776 innermost loop. */
fcf3be37
JJ
2777 if (n == 0 && mask_flag && forall_tmp->mask)
2778 {
2779 tree maskindex = forall_tmp->maskindex;
bc98ed60
TB
2780 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2781 maskindex, gfc_index_one_node);
726a989a 2782 gfc_add_modify (&block, maskindex, tmp);
fcf3be37
JJ
2783 }
2784
6de9cd9a 2785 /* Decrement the loop counter. */
bc98ed60
TB
2786 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2787 build_int_cst (TREE_TYPE (var), 1));
726a989a 2788 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
2789
2790 body = gfc_finish_block (&block);
2791
2792 /* Loop var initialization. */
2793 gfc_init_block (&block);
726a989a 2794 gfc_add_modify (&block, var, start);
6de9cd9a 2795
fcf3be37 2796
6de9cd9a 2797 /* Initialize the loop counter. */
bc98ed60
TB
2798 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2799 start);
2800 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2801 tmp);
2802 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2803 tmp, step);
726a989a 2804 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
2805
2806 /* The loop expression. */
923ab88c 2807 tmp = build1_v (LOOP_EXPR, body);
6de9cd9a
DN
2808 gfc_add_expr_to_block (&block, tmp);
2809
2810 /* The exit label. */
2811 tmp = build1_v (LABEL_EXPR, exit_label);
2812 gfc_add_expr_to_block (&block, tmp);
2813
2814 body = gfc_finish_block (&block);
2815 iter = iter->next;
2816 }
2817 return body;
2818}
2819
2820
bfcabc6c
RS
2821/* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2822 is nonzero, the body is controlled by all masks in the forall nest.
2823 Otherwise, the innermost loop is not controlled by it's mask. This
2824 is used for initializing that mask. */
6de9cd9a
DN
2825
2826static tree
2827gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
bfcabc6c 2828 int mask_flag)
6de9cd9a
DN
2829{
2830 tree tmp;
bfcabc6c 2831 stmtblock_t header;
6de9cd9a 2832 forall_info *forall_tmp;
bfcabc6c
RS
2833 tree mask, maskindex;
2834
2835 gfc_start_block (&header);
6de9cd9a
DN
2836
2837 forall_tmp = nested_forall_info;
bfcabc6c 2838 while (forall_tmp != NULL)
6de9cd9a 2839 {
bfcabc6c
RS
2840 /* Generate body with masks' control. */
2841 if (mask_flag)
6de9cd9a 2842 {
bfcabc6c
RS
2843 mask = forall_tmp->mask;
2844 maskindex = forall_tmp->maskindex;
6de9cd9a 2845
bfcabc6c
RS
2846 /* If a mask was specified make the assignment conditional. */
2847 if (mask)
2848 {
1d6b7f39 2849 tmp = gfc_build_array_ref (mask, maskindex, NULL);
c2255bc4
AH
2850 body = build3_v (COND_EXPR, tmp, body,
2851 build_empty_stmt (input_location));
6de9cd9a 2852 }
6de9cd9a 2853 }
bfcabc6c 2854 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
e8d366ec 2855 forall_tmp = forall_tmp->prev_nest;
bfcabc6c 2856 mask_flag = 1;
6de9cd9a
DN
2857 }
2858
bfcabc6c
RS
2859 gfc_add_expr_to_block (&header, body);
2860 return gfc_finish_block (&header);
6de9cd9a
DN
2861}
2862
2863
2864/* Allocate data for holding a temporary array. Returns either a local
2865 temporary array or a pointer variable. */
2866
2867static tree
2868gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2869 tree elem_type)
2870{
2871 tree tmpvar;
2872 tree type;
2873 tree tmp;
6de9cd9a
DN
2874
2875 if (INTEGER_CST_P (size))
bc98ed60
TB
2876 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2877 size, gfc_index_one_node);
6de9cd9a
DN
2878 else
2879 tmp = NULL_TREE;
2880
7ab92584 2881 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
6de9cd9a
DN
2882 type = build_array_type (elem_type, type);
2883 if (gfc_can_put_var_on_stack (bytesize))
2884 {
6e45f57b 2885 gcc_assert (INTEGER_CST_P (size));
6de9cd9a
DN
2886 tmpvar = gfc_create_var (type, "temp");
2887 *pdata = NULL_TREE;
2888 }
2889 else
2890 {
2891 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2892 *pdata = convert (pvoid_type_node, tmpvar);
2893
1529b8d9 2894 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
726a989a 2895 gfc_add_modify (pblock, tmpvar, tmp);
6de9cd9a
DN
2896 }
2897 return tmpvar;
2898}
2899
2900
2901/* Generate codes to copy the temporary to the actual lhs. */
2902
2903static tree
8de1f441 2904generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
011daa76 2905 tree count1, tree wheremask, bool invert)
6de9cd9a
DN
2906{
2907 gfc_ss *lss;
2908 gfc_se lse, rse;
2909 stmtblock_t block, body;
2910 gfc_loopinfo loop1;
011daa76 2911 tree tmp;
6de9cd9a
DN
2912 tree wheremaskexpr;
2913
2914 /* Walk the lhs. */
2915 lss = gfc_walk_expr (expr);
2916
2917 if (lss == gfc_ss_terminator)
2918 {
2919 gfc_start_block (&block);
2920
2921 gfc_init_se (&lse, NULL);
2922
2923 /* Translate the expression. */
2924 gfc_conv_expr (&lse, expr);
2925
2926 /* Form the expression for the temporary. */
1d6b7f39 2927 tmp = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2928
2929 /* Use the scalar assignment as is. */
2930 gfc_add_block_to_block (&block, &lse.pre);
726a989a 2931 gfc_add_modify (&block, lse.expr, tmp);
6de9cd9a
DN
2932 gfc_add_block_to_block (&block, &lse.post);
2933
2934 /* Increment the count1. */
bc98ed60
TB
2935 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2936 count1, gfc_index_one_node);
726a989a 2937 gfc_add_modify (&block, count1, tmp);
8de1f441 2938
6de9cd9a
DN
2939 tmp = gfc_finish_block (&block);
2940 }
2941 else
2942 {
2943 gfc_start_block (&block);
2944
2945 gfc_init_loopinfo (&loop1);
2946 gfc_init_se (&rse, NULL);
2947 gfc_init_se (&lse, NULL);
2948
2949 /* Associate the lss with the loop. */
2950 gfc_add_ss_to_loop (&loop1, lss);
2951
2952 /* Calculate the bounds of the scalarization. */
2953 gfc_conv_ss_startstride (&loop1);
2954 /* Setup the scalarizing loops. */
bdfd2ff0 2955 gfc_conv_loop_setup (&loop1, &expr->where);
6de9cd9a
DN
2956
2957 gfc_mark_ss_chain_used (lss, 1);
6de9cd9a
DN
2958
2959 /* Start the scalarized loop body. */
2960 gfc_start_scalarized_body (&loop1, &body);
2961
2962 /* Setup the gfc_se structures. */
2963 gfc_copy_loopinfo_to_se (&lse, &loop1);
2964 lse.ss = lss;
2965
2966 /* Form the expression of the temporary. */
2967 if (lss != gfc_ss_terminator)
1d6b7f39 2968 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2969 /* Translate expr. */
2970 gfc_conv_expr (&lse, expr);
2971
2972 /* Use the scalar assignment. */
5046aff5 2973 rse.string_length = lse.string_length;
2b56d6a4 2974 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
6de9cd9a 2975
011daa76
RS
2976 /* Form the mask expression according to the mask tree list. */
2977 if (wheremask)
2978 {
1d6b7f39 2979 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
011daa76 2980 if (invert)
bc98ed60
TB
2981 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2982 TREE_TYPE (wheremaskexpr),
2983 wheremaskexpr);
2984 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2985 wheremaskexpr, tmp,
2986 build_empty_stmt (input_location));
6de9cd9a
DN
2987 }
2988
2989 gfc_add_expr_to_block (&body, tmp);
2990
8de1f441 2991 /* Increment count1. */
bc98ed60
TB
2992 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2993 count1, gfc_index_one_node);
726a989a 2994 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
2995
2996 /* Increment count3. */
2997 if (count3)
8de1f441 2998 {
bc98ed60
TB
2999 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3000 gfc_array_index_type, count3,
3001 gfc_index_one_node);
726a989a 3002 gfc_add_modify (&body, count3, tmp);
8de1f441 3003 }
6de9cd9a
DN
3004
3005 /* Generate the copying loops. */
3006 gfc_trans_scalarizing_loops (&loop1, &body);
3007 gfc_add_block_to_block (&block, &loop1.pre);
3008 gfc_add_block_to_block (&block, &loop1.post);
3009 gfc_cleanup_loop (&loop1);
3010
6de9cd9a
DN
3011 tmp = gfc_finish_block (&block);
3012 }
3013 return tmp;
3014}
3015
3016
011daa76
RS
3017/* Generate codes to copy rhs to the temporary. TMP1 is the address of
3018 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3019 and should not be freed. WHEREMASK is the conditional execution mask
3020 whose sense may be inverted by INVERT. */
6de9cd9a
DN
3021
3022static tree
8de1f441
JJ
3023generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3024 tree count1, gfc_ss *lss, gfc_ss *rss,
011daa76 3025 tree wheremask, bool invert)
6de9cd9a
DN
3026{
3027 stmtblock_t block, body1;
3028 gfc_loopinfo loop;
3029 gfc_se lse;
3030 gfc_se rse;
011daa76 3031 tree tmp;
6de9cd9a
DN
3032 tree wheremaskexpr;
3033
3034 gfc_start_block (&block);
3035
3036 gfc_init_se (&rse, NULL);
3037 gfc_init_se (&lse, NULL);
3038
3039 if (lss == gfc_ss_terminator)
3040 {
3041 gfc_init_block (&body1);
3042 gfc_conv_expr (&rse, expr2);
1d6b7f39 3043 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
3044 }
3045 else
3046 {
1f2959f0 3047 /* Initialize the loop. */
6de9cd9a
DN
3048 gfc_init_loopinfo (&loop);
3049
3050 /* We may need LSS to determine the shape of the expression. */
3051 gfc_add_ss_to_loop (&loop, lss);
3052 gfc_add_ss_to_loop (&loop, rss);
3053
3054 gfc_conv_ss_startstride (&loop);
bdfd2ff0 3055 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
3056
3057 gfc_mark_ss_chain_used (rss, 1);
3058 /* Start the loop body. */
3059 gfc_start_scalarized_body (&loop, &body1);
3060
3061 /* Translate the expression. */
3062 gfc_copy_loopinfo_to_se (&rse, &loop);
3063 rse.ss = rss;
3064 gfc_conv_expr (&rse, expr2);
3065
3066 /* Form the expression of the temporary. */
1d6b7f39 3067 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
3068 }
3069
3070 /* Use the scalar assignment. */
5046aff5
PT
3071 lse.string_length = rse.string_length;
3072 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
2b56d6a4 3073 expr2->expr_type == EXPR_VARIABLE, true);
6de9cd9a
DN
3074
3075 /* Form the mask expression according to the mask tree list. */
3076 if (wheremask)
3077 {
1d6b7f39 3078 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
011daa76 3079 if (invert)
bc98ed60
TB
3080 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3081 TREE_TYPE (wheremaskexpr),
3082 wheremaskexpr);
3083 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3084 wheremaskexpr, tmp,
3085 build_empty_stmt (input_location));
6de9cd9a
DN
3086 }
3087
3088 gfc_add_expr_to_block (&body1, tmp);
3089
3090 if (lss == gfc_ss_terminator)
3091 {
3092 gfc_add_block_to_block (&block, &body1);
8de1f441
JJ
3093
3094 /* Increment count1. */
bc98ed60
TB
3095 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3096 count1, gfc_index_one_node);
726a989a 3097 gfc_add_modify (&block, count1, tmp);
6de9cd9a
DN
3098 }
3099 else
3100 {
8de1f441 3101 /* Increment count1. */
bc98ed60
TB
3102 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3103 count1, gfc_index_one_node);
726a989a 3104 gfc_add_modify (&body1, count1, tmp);
6de9cd9a
DN
3105
3106 /* Increment count3. */
3107 if (count3)
8de1f441 3108 {
bc98ed60
TB
3109 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3110 gfc_array_index_type,
3111 count3, gfc_index_one_node);
726a989a 3112 gfc_add_modify (&body1, count3, tmp);
8de1f441 3113 }
6de9cd9a
DN
3114
3115 /* Generate the copying loops. */
3116 gfc_trans_scalarizing_loops (&loop, &body1);
3117
3118 gfc_add_block_to_block (&block, &loop.pre);
3119 gfc_add_block_to_block (&block, &loop.post);
3120
3121 gfc_cleanup_loop (&loop);
3122 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
8de1f441 3123 as tree nodes in SS may not be valid in different scope. */
6de9cd9a 3124 }
6de9cd9a
DN
3125
3126 tmp = gfc_finish_block (&block);
3127 return tmp;
3128}
3129
3130
3131/* Calculate the size of temporary needed in the assignment inside forall.
3132 LSS and RSS are filled in this function. */
3133
3134static tree
3135compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3136 stmtblock_t * pblock,
3137 gfc_ss **lss, gfc_ss **rss)
3138{
3139 gfc_loopinfo loop;
3140 tree size;
3141 int i;
ca86ddcc 3142 int save_flag;
6de9cd9a
DN
3143 tree tmp;
3144
3145 *lss = gfc_walk_expr (expr1);
3146 *rss = NULL;
3147
7ab92584 3148 size = gfc_index_one_node;
6de9cd9a
DN
3149 if (*lss != gfc_ss_terminator)
3150 {
3151 gfc_init_loopinfo (&loop);
3152
3153 /* Walk the RHS of the expression. */
3154 *rss = gfc_walk_expr (expr2);
3155 if (*rss == gfc_ss_terminator)
26f77530
MM
3156 /* The rhs is scalar. Add a ss for the expression. */
3157 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
6de9cd9a
DN
3158
3159 /* Associate the SS with the loop. */
3160 gfc_add_ss_to_loop (&loop, *lss);
3161 /* We don't actually need to add the rhs at this point, but it might
3162 make guessing the loop bounds a bit easier. */
3163 gfc_add_ss_to_loop (&loop, *rss);
3164
3165 /* We only want the shape of the expression, not rest of the junk
3166 generated by the scalarizer. */
3167 loop.array_parameter = 1;
3168
3169 /* Calculate the bounds of the scalarization. */
d3d3011f 3170 save_flag = gfc_option.rtcheck;
c3fb8214 3171 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
6de9cd9a 3172 gfc_conv_ss_startstride (&loop);
d3d3011f 3173 gfc_option.rtcheck = save_flag;
bdfd2ff0 3174 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
3175
3176 /* Figure out how many elements we need. */
3177 for (i = 0; i < loop.dimen; i++)
3178 {
bc98ed60
TB
3179 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3180 gfc_array_index_type,
3181 gfc_index_one_node, loop.from[i]);
3182 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3183 gfc_array_index_type, tmp, loop.to[i]);
3184 size = fold_build2_loc (input_location, MULT_EXPR,
3185 gfc_array_index_type, size, tmp);
6de9cd9a
DN
3186 }
3187 gfc_add_block_to_block (pblock, &loop.pre);
3188 size = gfc_evaluate_now (size, pblock);
3189 gfc_add_block_to_block (pblock, &loop.post);
3190
3191 /* TODO: write a function that cleans up a loopinfo without freeing
3192 the SS chains. Currently a NOP. */
3193 }
3194
3195 return size;
3196}
3197
3198
2ad62c9b
RS
3199/* Calculate the overall iterator number of the nested forall construct.
3200 This routine actually calculates the number of times the body of the
3201 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3202 that by the expression INNER_SIZE. The BLOCK argument specifies the
3203 block in which to calculate the result, and the optional INNER_SIZE_BODY
3204 argument contains any statements that need to executed (inside the loop)
3205 to initialize or calculate INNER_SIZE. */
6de9cd9a
DN
3206
3207static tree
3208compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
8de1f441 3209 stmtblock_t *inner_size_body, stmtblock_t *block)
6de9cd9a 3210{
2ad62c9b 3211 forall_info *forall_tmp = nested_forall_info;
6de9cd9a
DN
3212 tree tmp, number;
3213 stmtblock_t body;
3214
2ad62c9b
RS
3215 /* We can eliminate the innermost unconditional loops with constant
3216 array bounds. */
3bf783b7
RS
3217 if (INTEGER_CST_P (inner_size))
3218 {
2ad62c9b 3219 while (forall_tmp
8b704316 3220 && !forall_tmp->mask
2ad62c9b 3221 && INTEGER_CST_P (forall_tmp->size))
3bf783b7 3222 {
bc98ed60
TB
3223 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3224 gfc_array_index_type,
3225 inner_size, forall_tmp->size);
2ad62c9b 3226 forall_tmp = forall_tmp->prev_nest;
3bf783b7 3227 }
2ad62c9b
RS
3228
3229 /* If there are no loops left, we have our constant result. */
3230 if (!forall_tmp)
3231 return inner_size;
3bf783b7 3232 }
2ad62c9b
RS
3233
3234 /* Otherwise, create a temporary variable to compute the result. */
6de9cd9a 3235 number = gfc_create_var (gfc_array_index_type, "num");
726a989a 3236 gfc_add_modify (block, number, gfc_index_zero_node);
6de9cd9a
DN
3237
3238 gfc_start_block (&body);
8de1f441
JJ
3239 if (inner_size_body)
3240 gfc_add_block_to_block (&body, inner_size_body);
2ad62c9b 3241 if (forall_tmp)
bc98ed60
TB
3242 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3243 gfc_array_index_type, number, inner_size);
6de9cd9a
DN
3244 else
3245 tmp = inner_size;
726a989a 3246 gfc_add_modify (&body, number, tmp);
6de9cd9a
DN
3247 tmp = gfc_finish_block (&body);
3248
3249 /* Generate loops. */
2ad62c9b
RS
3250 if (forall_tmp != NULL)
3251 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
6de9cd9a
DN
3252
3253 gfc_add_expr_to_block (block, tmp);
3254
3255 return number;
3256}
3257
3258
8de1f441
JJ
3259/* Allocate temporary for forall construct. SIZE is the size of temporary
3260 needed. PTEMP1 is returned for space free. */
6de9cd9a
DN
3261
3262static tree
8de1f441
JJ
3263allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3264 tree * ptemp1)
6de9cd9a 3265{
bfcabc6c 3266 tree bytesize;
6de9cd9a 3267 tree unit;
6de9cd9a 3268 tree tmp;
6de9cd9a 3269
7c57b2f1 3270 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
bfcabc6c 3271 if (!integer_onep (unit))
bc98ed60
TB
3272 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3273 gfc_array_index_type, size, unit);
bfcabc6c
RS
3274 else
3275 bytesize = size;
6de9cd9a
DN
3276
3277 *ptemp1 = NULL;
bfcabc6c 3278 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
6de9cd9a
DN
3279
3280 if (*ptemp1)
db3927fb 3281 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6de9cd9a
DN
3282 return tmp;
3283}
3284
3285
8de1f441
JJ
3286/* Allocate temporary for forall construct according to the information in
3287 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3288 assignment inside forall. PTEMP1 is returned for space free. */
3289
3290static tree
3291allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3292 tree inner_size, stmtblock_t * inner_size_body,
3293 stmtblock_t * block, tree * ptemp1)
3294{
3295 tree size;
3296
3297 /* Calculate the total size of temporary needed in forall construct. */
3298 size = compute_overall_iter_number (nested_forall_info, inner_size,
3299 inner_size_body, block);
3300
3301 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3302}
3303
3304
3305/* Handle assignments inside forall which need temporary.
3306
3307 forall (i=start:end:stride; maskexpr)
3308 e<i> = f<i>
3309 end forall
3310 (where e,f<i> are arbitrary expressions possibly involving i
3311 and there is a dependency between e<i> and f<i>)
3312 Translates to:
3313 masktmp(:) = maskexpr(:)
3314
3315 maskindex = 0;
3316 count1 = 0;
3317 num = 0;
3318 for (i = start; i <= end; i += stride)
3319 num += SIZE (f<i>)
3320 count1 = 0;
3321 ALLOCATE (tmp(num))
3322 for (i = start; i <= end; i += stride)
3323 {
3324 if (masktmp[maskindex++])
3325 tmp[count1++] = f<i>
3326 }
3327 maskindex = 0;
3328 count1 = 0;
3329 for (i = start; i <= end; i += stride)
3330 {
3331 if (masktmp[maskindex++])
3332 e<i> = tmp[count1++]
3333 }
3334 DEALLOCATE (tmp)
3335 */
6de9cd9a 3336static void
011daa76
RS
3337gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3338 tree wheremask, bool invert,
6de9cd9a
DN
3339 forall_info * nested_forall_info,
3340 stmtblock_t * block)
3341{
3342 tree type;
3343 tree inner_size;
3344 gfc_ss *lss, *rss;
8de1f441 3345 tree count, count1;
6de9cd9a
DN
3346 tree tmp, tmp1;
3347 tree ptemp1;
8de1f441 3348 stmtblock_t inner_size_body;
6de9cd9a 3349
8de1f441
JJ
3350 /* Create vars. count1 is the current iterator number of the nested
3351 forall. */
6de9cd9a 3352 count1 = gfc_create_var (gfc_array_index_type, "count1");
6de9cd9a
DN
3353
3354 /* Count is the wheremask index. */
3355 if (wheremask)
3356 {
3357 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 3358 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
3359 }
3360 else
3361 count = NULL;
3362
3363 /* Initialize count1. */
726a989a 3364 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a
DN
3365
3366 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3367 and rss which are used in function generate_loop_for_rhs_to_temp(). */
8de1f441
JJ
3368 gfc_init_block (&inner_size_body);
3369 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3370 &lss, &rss);
6de9cd9a
DN
3371
3372 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
bc21d315 3373 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
640670c7 3374 {
bc21d315 3375 if (!expr1->ts.u.cl->backend_decl)
640670c7
PT
3376 {
3377 gfc_se tse;
3378 gfc_init_se (&tse, NULL);
bc21d315
JW
3379 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3380 expr1->ts.u.cl->backend_decl = tse.expr;
640670c7
PT
3381 }
3382 type = gfc_get_character_type_len (gfc_default_character_kind,
bc21d315 3383 expr1->ts.u.cl->backend_decl);
640670c7
PT
3384 }
3385 else
3386 type = gfc_typenode_for_spec (&expr1->ts);
6de9cd9a
DN
3387
3388 /* Allocate temporary for nested forall construct according to the
f7b529fa 3389 information in nested_forall_info and inner_size. */
8de1f441
JJ
3390 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3391 &inner_size_body, block, &ptemp1);
6de9cd9a 3392
6de9cd9a 3393 /* Generate codes to copy rhs to the temporary . */
8de1f441 3394 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
011daa76 3395 wheremask, invert);
6de9cd9a 3396
1f2959f0 3397 /* Generate body and loops according to the information in
6de9cd9a 3398 nested_forall_info. */
bfcabc6c 3399 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
3400 gfc_add_expr_to_block (block, tmp);
3401
3402 /* Reset count1. */
726a989a 3403 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a 3404
6de9cd9a
DN
3405 /* Reset count. */
3406 if (wheremask)
726a989a 3407 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
3408
3409 /* Generate codes to copy the temporary to lhs. */
011daa76
RS
3410 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3411 wheremask, invert);
6de9cd9a 3412
1f2959f0 3413 /* Generate body and loops according to the information in
6de9cd9a 3414 nested_forall_info. */
bfcabc6c 3415 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
3416 gfc_add_expr_to_block (block, tmp);
3417
3418 if (ptemp1)
3419 {
3420 /* Free the temporary. */
1529b8d9 3421 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
3422 gfc_add_expr_to_block (block, tmp);
3423 }
3424}
3425
3426
3427/* Translate pointer assignment inside FORALL which need temporary. */
3428
3429static void
3430gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3431 forall_info * nested_forall_info,
3432 stmtblock_t * block)
3433{
3434 tree type;
3435 tree inner_size;
3436 gfc_ss *lss, *rss;
3437 gfc_se lse;
3438 gfc_se rse;
6d63e468 3439 gfc_array_info *info;
6de9cd9a
DN
3440 gfc_loopinfo loop;
3441 tree desc;
3442 tree parm;
3443 tree parmtype;
3444 stmtblock_t body;
3445 tree count;
3446 tree tmp, tmp1, ptemp1;
6de9cd9a
DN
3447
3448 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 3449 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 3450
932ebb94 3451 inner_size = gfc_index_one_node;
6de9cd9a
DN
3452 lss = gfc_walk_expr (expr1);
3453 rss = gfc_walk_expr (expr2);
3454 if (lss == gfc_ss_terminator)
3455 {
3456 type = gfc_typenode_for_spec (&expr1->ts);
3457 type = build_pointer_type (type);
3458
3459 /* Allocate temporary for nested forall construct according to the
3460 information in nested_forall_info and inner_size. */
8de1f441
JJ
3461 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3462 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
3463 gfc_start_block (&body);
3464 gfc_init_se (&lse, NULL);
1d6b7f39 3465 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
3466 gfc_init_se (&rse, NULL);
3467 rse.want_pointer = 1;
3468 gfc_conv_expr (&rse, expr2);
3469 gfc_add_block_to_block (&body, &rse.pre);
726a989a 3470 gfc_add_modify (&body, lse.expr,
cc2804f1 3471 fold_convert (TREE_TYPE (lse.expr), rse.expr));
6de9cd9a
DN
3472 gfc_add_block_to_block (&body, &rse.post);
3473
3474 /* Increment count. */
bc98ed60
TB
3475 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3476 count, gfc_index_one_node);
726a989a 3477 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
3478
3479 tmp = gfc_finish_block (&body);
3480
1f2959f0 3481 /* Generate body and loops according to the information in
6de9cd9a 3482 nested_forall_info. */
bfcabc6c 3483 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
3484 gfc_add_expr_to_block (block, tmp);
3485
3486 /* Reset count. */
726a989a 3487 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 3488
6de9cd9a
DN
3489 gfc_start_block (&body);
3490 gfc_init_se (&lse, NULL);
3491 gfc_init_se (&rse, NULL);
1d6b7f39 3492 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
3493 lse.want_pointer = 1;
3494 gfc_conv_expr (&lse, expr1);
3495 gfc_add_block_to_block (&body, &lse.pre);
726a989a 3496 gfc_add_modify (&body, lse.expr, rse.expr);
6de9cd9a
DN
3497 gfc_add_block_to_block (&body, &lse.post);
3498 /* Increment count. */
bc98ed60
TB
3499 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3500 count, gfc_index_one_node);
726a989a 3501 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
3502 tmp = gfc_finish_block (&body);
3503
1f2959f0 3504 /* Generate body and loops according to the information in
6de9cd9a 3505 nested_forall_info. */
bfcabc6c 3506 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
3507 gfc_add_expr_to_block (block, tmp);
3508 }
3509 else
3510 {
3511 gfc_init_loopinfo (&loop);
3512
3513 /* Associate the SS with the loop. */
3514 gfc_add_ss_to_loop (&loop, rss);
3515
3516 /* Setup the scalarizing loops and bounds. */
3517 gfc_conv_ss_startstride (&loop);
3518
bdfd2ff0 3519 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a 3520
1838afec 3521 info = &rss->info->data.array;
6de9cd9a
DN
3522 desc = info->descriptor;
3523
3524 /* Make a new descriptor. */
3525 parmtype = gfc_get_element_type (TREE_TYPE (desc));
f33beee9 3526 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
fad0afd7 3527 loop.from, loop.to, 1,
10174ddf 3528 GFC_ARRAY_UNKNOWN, true);
6de9cd9a
DN
3529
3530 /* Allocate temporary for nested forall construct. */
3531 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
8de1f441 3532 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
3533 gfc_start_block (&body);
3534 gfc_init_se (&lse, NULL);
1d6b7f39 3535 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a 3536 lse.direct_byref = 1;
2960a368 3537 gfc_conv_expr_descriptor (&lse, expr2);
6de9cd9a
DN
3538
3539 gfc_add_block_to_block (&body, &lse.pre);
3540 gfc_add_block_to_block (&body, &lse.post);
3541
3542 /* Increment count. */
bc98ed60
TB
3543 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3544 count, gfc_index_one_node);
726a989a 3545 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
3546
3547 tmp = gfc_finish_block (&body);
3548
1f2959f0 3549 /* Generate body and loops according to the information in
6de9cd9a 3550 nested_forall_info. */
bfcabc6c 3551 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
3552 gfc_add_expr_to_block (block, tmp);
3553
3554 /* Reset count. */
726a989a 3555 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 3556
1d6b7f39 3557 parm = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a 3558 gfc_init_se (&lse, NULL);
2960a368 3559 gfc_conv_expr_descriptor (&lse, expr1);
726a989a 3560 gfc_add_modify (&lse.pre, lse.expr, parm);
6de9cd9a
DN
3561 gfc_start_block (&body);
3562 gfc_add_block_to_block (&body, &lse.pre);
3563 gfc_add_block_to_block (&body, &lse.post);
3564
3565 /* Increment count. */
bc98ed60
TB
3566 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3567 count, gfc_index_one_node);
726a989a 3568 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
3569
3570 tmp = gfc_finish_block (&body);
3571
bfcabc6c 3572 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
3573 gfc_add_expr_to_block (block, tmp);
3574 }
3575 /* Free the temporary. */
3576 if (ptemp1)
3577 {
1529b8d9 3578 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
3579 gfc_add_expr_to_block (block, tmp);
3580 }
3581}
3582
3583
3584/* FORALL and WHERE statements are really nasty, especially when you nest
3585 them. All the rhs of a forall assignment must be evaluated before the
3586 actual assignments are performed. Presumably this also applies to all the
3587 assignments in an inner where statement. */
3588
3589/* Generate code for a FORALL statement. Any temporaries are allocated as a
3590 linear array, relying on the fact that we process in the same order in all
3591 loops.
3592
3593 forall (i=start:end:stride; maskexpr)
3594 e<i> = f<i>
3595 g<i> = h<i>
3596 end forall
e7dc5b4f 3597 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
6de9cd9a 3598 Translates to:
8de1f441 3599 count = ((end + 1 - start) / stride)
6de9cd9a
DN
3600 masktmp(:) = maskexpr(:)
3601
3602 maskindex = 0;
3603 for (i = start; i <= end; i += stride)
3604 {
3605 if (masktmp[maskindex++])
3606 e<i> = f<i>
3607 }
3608 maskindex = 0;
3609 for (i = start; i <= end; i += stride)
3610 {
3611 if (masktmp[maskindex++])
cafa34aa 3612 g<i> = h<i>
6de9cd9a
DN
3613 }
3614
3615 Note that this code only works when there are no dependencies.
3616 Forall loop with array assignments and data dependencies are a real pain,
3617 because the size of the temporary cannot always be determined before the
1f2959f0 3618 loop is executed. This problem is compounded by the presence of nested
6de9cd9a
DN
3619 FORALL constructs.
3620 */
3621
3622static tree
3623gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3624{
640670c7
PT
3625 stmtblock_t pre;
3626 stmtblock_t post;
6de9cd9a
DN
3627 stmtblock_t block;
3628 stmtblock_t body;
3629 tree *var;
3630 tree *start;
3631 tree *end;
3632 tree *step;
3633 gfc_expr **varexpr;
3634 tree tmp;
3635 tree assign;
3636 tree size;
6de9cd9a
DN
3637 tree maskindex;
3638 tree mask;
3639 tree pmask;
8c6a85e3 3640 tree cycle_label = NULL_TREE;
6de9cd9a
DN
3641 int n;
3642 int nvar;
3643 int need_temp;
3644 gfc_forall_iterator *fa;
3645 gfc_se se;
3646 gfc_code *c;
7b5b57b7 3647 gfc_saved_var *saved_vars;
bfcabc6c
RS
3648 iter_info *this_forall;
3649 forall_info *info;
e35a0e64
RS
3650 bool need_mask;
3651
3652 /* Do nothing if the mask is false. */
a513927a
SK
3653 if (code->expr1
3654 && code->expr1->expr_type == EXPR_CONSTANT
3655 && !code->expr1->value.logical)
c2255bc4 3656 return build_empty_stmt (input_location);
6de9cd9a
DN
3657
3658 n = 0;
3659 /* Count the FORALL index number. */
3660 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3661 n++;
3662 nvar = n;
3663
3664 /* Allocate the space for var, start, end, step, varexpr. */
93acb62c
JB
3665 var = XCNEWVEC (tree, nvar);
3666 start = XCNEWVEC (tree, nvar);
3667 end = XCNEWVEC (tree, nvar);
3668 step = XCNEWVEC (tree, nvar);
3669 varexpr = XCNEWVEC (gfc_expr *, nvar);
3670 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
6de9cd9a
DN
3671
3672 /* Allocate the space for info. */
93acb62c 3673 info = XCNEW (forall_info);
bfcabc6c 3674
640670c7
PT
3675 gfc_start_block (&pre);
3676 gfc_init_block (&post);
3677 gfc_init_block (&block);
bfcabc6c 3678
6de9cd9a
DN
3679 n = 0;
3680 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3681 {
3682 gfc_symbol *sym = fa->var->symtree->n.sym;
3683
bfcabc6c 3684 /* Allocate space for this_forall. */
93acb62c 3685 this_forall = XCNEW (iter_info);
6de9cd9a 3686
6de9cd9a
DN
3687 /* Create a temporary variable for the FORALL index. */
3688 tmp = gfc_typenode_for_spec (&sym->ts);
3689 var[n] = gfc_create_var (tmp, sym->name);
7b5b57b7
PB
3690 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3691
6de9cd9a
DN
3692 /* Record it in this_forall. */
3693 this_forall->var = var[n];
3694
3695 /* Replace the index symbol's backend_decl with the temporary decl. */
3696 sym->backend_decl = var[n];
3697
3698 /* Work out the start, end and stride for the loop. */
3699 gfc_init_se (&se, NULL);
3700 gfc_conv_expr_val (&se, fa->start);
3701 /* Record it in this_forall. */
3702 this_forall->start = se.expr;
3703 gfc_add_block_to_block (&block, &se.pre);
3704 start[n] = se.expr;
3705
3706 gfc_init_se (&se, NULL);
3707 gfc_conv_expr_val (&se, fa->end);
3708 /* Record it in this_forall. */
3709 this_forall->end = se.expr;
3710 gfc_make_safe_expr (&se);
3711 gfc_add_block_to_block (&block, &se.pre);
3712 end[n] = se.expr;
3713
3714 gfc_init_se (&se, NULL);
3715 gfc_conv_expr_val (&se, fa->stride);
3716 /* Record it in this_forall. */
3717 this_forall->step = se.expr;
3718 gfc_make_safe_expr (&se);
3719 gfc_add_block_to_block (&block, &se.pre);
3720 step[n] = se.expr;
3721
3722 /* Set the NEXT field of this_forall to NULL. */
3723 this_forall->next = NULL;
3724 /* Link this_forall to the info construct. */
bfcabc6c 3725 if (info->this_loop)
6de9cd9a 3726 {
bfcabc6c 3727 iter_info *iter_tmp = info->this_loop;
6de9cd9a
DN
3728 while (iter_tmp->next != NULL)
3729 iter_tmp = iter_tmp->next;
3730 iter_tmp->next = this_forall;
3731 }
bfcabc6c
RS
3732 else
3733 info->this_loop = this_forall;
6de9cd9a
DN
3734
3735 n++;
3736 }
3737 nvar = n;
3738
bfcabc6c 3739 /* Calculate the size needed for the current forall level. */
7ab92584 3740 size = gfc_index_one_node;
6de9cd9a
DN
3741 for (n = 0; n < nvar; n++)
3742 {
6de9cd9a 3743 /* size = (end + step - start) / step. */
8b704316 3744 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
bc98ed60
TB
3745 step[n], start[n]);
3746 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3747 end[n], tmp);
3748 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3749 tmp, step[n]);
6de9cd9a
DN
3750 tmp = convert (gfc_array_index_type, tmp);
3751
bc98ed60
TB
3752 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3753 size, tmp);
6de9cd9a
DN
3754 }
3755
3756 /* Record the nvar and size of current forall level. */
3757 info->nvar = nvar;
3758 info->size = size;
3759
a513927a 3760 if (code->expr1)
e35a0e64
RS
3761 {
3762 /* If the mask is .true., consider the FORALL unconditional. */
a513927a
SK
3763 if (code->expr1->expr_type == EXPR_CONSTANT
3764 && code->expr1->value.logical)
e35a0e64
RS
3765 need_mask = false;
3766 else
3767 need_mask = true;
3768 }
3769 else
3770 need_mask = false;
3771
3772 /* First we need to allocate the mask. */
3773 if (need_mask)
bfcabc6c
RS
3774 {
3775 /* As the mask array can be very big, prefer compact boolean types. */
3776 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3777 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3778 size, NULL, &block, &pmask);
3779 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3780
3781 /* Record them in the info structure. */
3782 info->maskindex = maskindex;
3783 info->mask = mask;
3784 }
6de9cd9a
DN
3785 else
3786 {
bfcabc6c
RS
3787 /* No mask was specified. */
3788 maskindex = NULL_TREE;
3789 mask = pmask = NULL_TREE;
3790 }
3791
3792 /* Link the current forall level to nested_forall_info. */
e8d366ec
RS
3793 info->prev_nest = nested_forall_info;
3794 nested_forall_info = info;
6de9cd9a
DN
3795
3796 /* Copy the mask into a temporary variable if required.
f7b529fa 3797 For now we assume a mask temporary is needed. */
e35a0e64 3798 if (need_mask)
6de9cd9a 3799 {
bfcabc6c
RS
3800 /* As the mask array can be very big, prefer compact boolean types. */
3801 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
6de9cd9a 3802
726a989a 3803 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
6de9cd9a
DN
3804
3805 /* Start of mask assignment loop body. */
3806 gfc_start_block (&body);
3807
3808 /* Evaluate the mask expression. */
3809 gfc_init_se (&se, NULL);
a513927a 3810 gfc_conv_expr_val (&se, code->expr1);
6de9cd9a
DN
3811 gfc_add_block_to_block (&body, &se.pre);
3812
3813 /* Store the mask. */
bfcabc6c 3814 se.expr = convert (mask_type, se.expr);
6de9cd9a 3815
1d6b7f39 3816 tmp = gfc_build_array_ref (mask, maskindex, NULL);
726a989a 3817 gfc_add_modify (&body, tmp, se.expr);
6de9cd9a
DN
3818
3819 /* Advance to the next mask element. */
bc98ed60
TB
3820 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3821 maskindex, gfc_index_one_node);
726a989a 3822 gfc_add_modify (&body, maskindex, tmp);
6de9cd9a
DN
3823
3824 /* Generate the loops. */
3825 tmp = gfc_finish_block (&body);
bfcabc6c 3826 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
6de9cd9a
DN
3827 gfc_add_expr_to_block (&block, tmp);
3828 }
6de9cd9a 3829
8c6a85e3
TB
3830 if (code->op == EXEC_DO_CONCURRENT)
3831 {
3832 gfc_init_block (&body);
3833 cycle_label = gfc_build_label_decl (NULL_TREE);
3834 code->cycle_label = cycle_label;
3835 tmp = gfc_trans_code (code->block->next);
3836 gfc_add_expr_to_block (&body, tmp);
3837
3838 if (TREE_USED (cycle_label))
3839 {
3840 tmp = build1_v (LABEL_EXPR, cycle_label);
3841 gfc_add_expr_to_block (&body, tmp);
3842 }
3843
3844 tmp = gfc_finish_block (&body);
3845 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3846 gfc_add_expr_to_block (&block, tmp);
3847 goto done;
3848 }
3849
6de9cd9a
DN
3850 c = code->block->next;
3851
3852 /* TODO: loop merging in FORALL statements. */
3853 /* Now that we've got a copy of the mask, generate the assignment loops. */
3854 while (c)
3855 {
3856 switch (c->op)
3857 {
3858 case EXEC_ASSIGN:
640670c7
PT
3859 /* A scalar or array assignment. DO the simple check for
3860 lhs to rhs dependencies. These make a temporary for the
3861 rhs and form a second forall block to copy to variable. */
3862 need_temp = check_forall_dependencies(c, &pre, &post);
3863
69de3b83 3864 /* Temporaries due to array assignment data dependencies introduce
6de9cd9a
DN
3865 no end of problems. */
3866 if (need_temp)
a513927a 3867 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
6de9cd9a
DN
3868 nested_forall_info, &block);
3869 else
3870 {
3871 /* Use the normal assignment copying routines. */
2b56d6a4 3872 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
6de9cd9a 3873
6de9cd9a 3874 /* Generate body and loops. */
bfcabc6c
RS
3875 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3876 assign, 1);
6de9cd9a
DN
3877 gfc_add_expr_to_block (&block, tmp);
3878 }
3879
640670c7
PT
3880 /* Cleanup any temporary symtrees that have been made to deal
3881 with dependencies. */
3882 if (new_symtree)
3883 cleanup_forall_symtrees (c);
3884
6de9cd9a
DN
3885 break;
3886
3887 case EXEC_WHERE:
6de9cd9a 3888 /* Translate WHERE or WHERE construct nested in FORALL. */
011daa76 3889 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3891cee2 3890 break;
6de9cd9a
DN
3891
3892 /* Pointer assignment inside FORALL. */
3893 case EXEC_POINTER_ASSIGN:
a513927a 3894 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
6de9cd9a 3895 if (need_temp)
a513927a 3896 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
6de9cd9a
DN
3897 nested_forall_info, &block);
3898 else
3899 {
3900 /* Use the normal assignment copying routines. */
a513927a 3901 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
6de9cd9a 3902
6de9cd9a 3903 /* Generate body and loops. */
bfcabc6c
RS
3904 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3905 assign, 1);
6de9cd9a
DN
3906 gfc_add_expr_to_block (&block, tmp);
3907 }
3908 break;
3909
3910 case EXEC_FORALL:
3911 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3912 gfc_add_expr_to_block (&block, tmp);
3913 break;
3914
48474141
PT
3915 /* Explicit subroutine calls are prevented by the frontend but interface
3916 assignments can legitimately produce them. */
476220e7 3917 case EXEC_ASSIGN_CALL:
eb74e79b 3918 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
bfcabc6c 3919 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
48474141
PT
3920 gfc_add_expr_to_block (&block, tmp);
3921 break;
3922
6de9cd9a 3923 default:
6e45f57b 3924 gcc_unreachable ();
6de9cd9a
DN
3925 }
3926
3927 c = c->next;
3928 }
3929
8c6a85e3 3930done:
7b5b57b7
PB
3931 /* Restore the original index variables. */
3932 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3933 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
6de9cd9a
DN
3934
3935 /* Free the space for var, start, end, step, varexpr. */
cede9502
JM
3936 free (var);
3937 free (start);
3938 free (end);
3939 free (step);
3940 free (varexpr);
3941 free (saved_vars);
6de9cd9a 3942
3231fe90
MM
3943 for (this_forall = info->this_loop; this_forall;)
3944 {
3945 iter_info *next = this_forall->next;
cede9502 3946 free (this_forall);
3231fe90
MM
3947 this_forall = next;
3948 }
3949
e8d366ec 3950 /* Free the space for this forall_info. */
cede9502 3951 free (info);
e8d366ec 3952
6de9cd9a
DN
3953 if (pmask)
3954 {
3955 /* Free the temporary for the mask. */
1529b8d9 3956 tmp = gfc_call_free (pmask);
6de9cd9a
DN
3957 gfc_add_expr_to_block (&block, tmp);
3958 }
3959 if (maskindex)
3960 pushdecl (maskindex);
3961
640670c7
PT
3962 gfc_add_block_to_block (&pre, &block);
3963 gfc_add_block_to_block (&pre, &post);
3964
3965 return gfc_finish_block (&pre);
6de9cd9a
DN
3966}
3967
3968
3969/* Translate the FORALL statement or construct. */
3970
3971tree gfc_trans_forall (gfc_code * code)
3972{
3973 return gfc_trans_forall_1 (code, NULL);
3974}
3975
3976
8c6a85e3
TB
3977/* Translate the DO CONCURRENT construct. */
3978
3979tree gfc_trans_do_concurrent (gfc_code * code)
3980{
3981 return gfc_trans_forall_1 (code, NULL);
3982}
3983
3984
6de9cd9a
DN
3985/* Evaluate the WHERE mask expression, copy its value to a temporary.
3986 If the WHERE construct is nested in FORALL, compute the overall temporary
3987 needed by the WHERE mask expression multiplied by the iterator number of
3988 the nested forall.
3989 ME is the WHERE mask expression.
011daa76
RS
3990 MASK is the current execution mask upon input, whose sense may or may
3991 not be inverted as specified by the INVERT argument.
3891cee2
RS
3992 CMASK is the updated execution mask on output, or NULL if not required.
3993 PMASK is the pending execution mask on output, or NULL if not required.
3994 BLOCK is the block in which to place the condition evaluation loops. */
6de9cd9a 3995
3891cee2 3996static void
6de9cd9a 3997gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
011daa76 3998 tree mask, bool invert, tree cmask, tree pmask,
3891cee2 3999 tree mask_type, stmtblock_t * block)
6de9cd9a
DN
4000{
4001 tree tmp, tmp1;
4002 gfc_ss *lss, *rss;
4003 gfc_loopinfo loop;
3891cee2
RS
4004 stmtblock_t body, body1;
4005 tree count, cond, mtmp;
6de9cd9a 4006 gfc_se lse, rse;
6de9cd9a
DN
4007
4008 gfc_init_loopinfo (&loop);
4009
3891cee2
RS
4010 lss = gfc_walk_expr (me);
4011 rss = gfc_walk_expr (me);
6de9cd9a
DN
4012
4013 /* Variable to index the temporary. */
4014 count = gfc_create_var (gfc_array_index_type, "count");
1f2959f0 4015 /* Initialize count. */
726a989a 4016 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
4017
4018 gfc_start_block (&body);
4019
4020 gfc_init_se (&rse, NULL);
4021 gfc_init_se (&lse, NULL);
4022
4023 if (lss == gfc_ss_terminator)
4024 {
4025 gfc_init_block (&body1);
4026 }
4027 else
4028 {
1f2959f0 4029 /* Initialize the loop. */
6de9cd9a
DN
4030 gfc_init_loopinfo (&loop);
4031
4032 /* We may need LSS to determine the shape of the expression. */
4033 gfc_add_ss_to_loop (&loop, lss);
4034 gfc_add_ss_to_loop (&loop, rss);
4035
4036 gfc_conv_ss_startstride (&loop);
bdfd2ff0 4037 gfc_conv_loop_setup (&loop, &me->where);
6de9cd9a
DN
4038
4039 gfc_mark_ss_chain_used (rss, 1);
4040 /* Start the loop body. */
4041 gfc_start_scalarized_body (&loop, &body1);
4042
4043 /* Translate the expression. */
4044 gfc_copy_loopinfo_to_se (&rse, &loop);
4045 rse.ss = rss;
4046 gfc_conv_expr (&rse, me);
4047 }
6de9cd9a 4048
b82feea5 4049 /* Variable to evaluate mask condition. */
3891cee2
RS
4050 cond = gfc_create_var (mask_type, "cond");
4051 if (mask && (cmask || pmask))
4052 mtmp = gfc_create_var (mask_type, "mask");
4053 else mtmp = NULL_TREE;
4054
4055 gfc_add_block_to_block (&body1, &lse.pre);
4056 gfc_add_block_to_block (&body1, &rse.pre);
6de9cd9a 4057
726a989a 4058 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
3891cee2
RS
4059
4060 if (mask && (cmask || pmask))
42e73749 4061 {
1d6b7f39 4062 tmp = gfc_build_array_ref (mask, count, NULL);
011daa76 4063 if (invert)
bc98ed60 4064 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
726a989a 4065 gfc_add_modify (&body1, mtmp, tmp);
42e73749 4066 }
6de9cd9a 4067
3891cee2
RS
4068 if (cmask)
4069 {
1d6b7f39 4070 tmp1 = gfc_build_array_ref (cmask, count, NULL);
3891cee2
RS
4071 tmp = cond;
4072 if (mask)
bc98ed60
TB
4073 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4074 mtmp, tmp);
726a989a 4075 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
4076 }
4077
4078 if (pmask)
4079 {
1d6b7f39 4080 tmp1 = gfc_build_array_ref (pmask, count, NULL);
bc98ed60 4081 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
3891cee2 4082 if (mask)
bc98ed60
TB
4083 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4084 tmp);
726a989a 4085 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
4086 }
4087
4088 gfc_add_block_to_block (&body1, &lse.post);
4089 gfc_add_block_to_block (&body1, &rse.post);
4090
4091 if (lss == gfc_ss_terminator)
6de9cd9a
DN
4092 {
4093 gfc_add_block_to_block (&body, &body1);
4094 }
4095 else
4096 {
4097 /* Increment count. */
bc98ed60
TB
4098 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4099 count, gfc_index_one_node);
726a989a 4100 gfc_add_modify (&body1, count, tmp1);
6de9cd9a
DN
4101
4102 /* Generate the copying loops. */
4103 gfc_trans_scalarizing_loops (&loop, &body1);
4104
4105 gfc_add_block_to_block (&body, &loop.pre);
4106 gfc_add_block_to_block (&body, &loop.post);
4107
4108 gfc_cleanup_loop (&loop);
4109 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4110 as tree nodes in SS may not be valid in different scope. */
4111 }
4112
4113 tmp1 = gfc_finish_block (&body);
4114 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4115 if (nested_forall_info != NULL)
bfcabc6c 4116 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
6de9cd9a
DN
4117
4118 gfc_add_expr_to_block (block, tmp1);
6de9cd9a
DN
4119}
4120
4121
4122/* Translate an assignment statement in a WHERE statement or construct
4123 statement. The MASK expression is used to control which elements
011daa76
RS
4124 of EXPR1 shall be assigned. The sense of MASK is specified by
4125 INVERT. */
6de9cd9a
DN
4126
4127static tree
011daa76
RS
4128gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4129 tree mask, bool invert,
a00b8d1a 4130 tree count1, tree count2,
eb74e79b 4131 gfc_code *cnext)
6de9cd9a
DN
4132{
4133 gfc_se lse;
4134 gfc_se rse;
4135 gfc_ss *lss;
4136 gfc_ss *lss_section;
4137 gfc_ss *rss;
4138
4139 gfc_loopinfo loop;
4140 tree tmp;
4141 stmtblock_t block;
4142 stmtblock_t body;
3c90c9ae 4143 tree index, maskexpr;
6de9cd9a 4144
8b704316 4145 /* A defined assignment. */
eb74e79b
PT
4146 if (cnext && cnext->resolved_sym)
4147 return gfc_trans_call (cnext, true, mask, count1, invert);
4148
6de9cd9a
DN
4149#if 0
4150 /* TODO: handle this special case.
4151 Special case a single function returning an array. */
4152 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4153 {
4154 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4155 if (tmp)
4156 return tmp;
4157 }
4158#endif
4159
4160 /* Assignment of the form lhs = rhs. */
4161 gfc_start_block (&block);
4162
4163 gfc_init_se (&lse, NULL);
4164 gfc_init_se (&rse, NULL);
4165
4166 /* Walk the lhs. */
4167 lss = gfc_walk_expr (expr1);
4168 rss = NULL;
4169
4170 /* In each where-assign-stmt, the mask-expr and the variable being
4171 defined shall be arrays of the same shape. */
6e45f57b 4172 gcc_assert (lss != gfc_ss_terminator);
6de9cd9a
DN
4173
4174 /* The assignment needs scalarization. */
4175 lss_section = lss;
4176
4177 /* Find a non-scalar SS from the lhs. */
4178 while (lss_section != gfc_ss_terminator
bcc4d4e0 4179 && lss_section->info->type != GFC_SS_SECTION)
6de9cd9a
DN
4180 lss_section = lss_section->next;
4181
6e45f57b 4182 gcc_assert (lss_section != gfc_ss_terminator);
6de9cd9a
DN
4183
4184 /* Initialize the scalarizer. */
4185 gfc_init_loopinfo (&loop);
4186
4187 /* Walk the rhs. */
4188 rss = gfc_walk_expr (expr2);
4189 if (rss == gfc_ss_terminator)
26f77530
MM
4190 {
4191 /* The rhs is scalar. Add a ss for the expression. */
4192 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
42d0058e 4193 rss->info->where = 1;
6de9cd9a
DN
4194 }
4195
4196 /* Associate the SS with the loop. */
4197 gfc_add_ss_to_loop (&loop, lss);
4198 gfc_add_ss_to_loop (&loop, rss);
4199
4200 /* Calculate the bounds of the scalarization. */
4201 gfc_conv_ss_startstride (&loop);
4202
4203 /* Resolve any data dependencies in the statement. */
4204 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4205
4206 /* Setup the scalarizing loops. */
bdfd2ff0 4207 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
4208
4209 /* Setup the gfc_se structures. */
4210 gfc_copy_loopinfo_to_se (&lse, &loop);
4211 gfc_copy_loopinfo_to_se (&rse, &loop);
4212
4213 rse.ss = rss;
4214 gfc_mark_ss_chain_used (rss, 1);
4215 if (loop.temp_ss == NULL)
4216 {
4217 lse.ss = lss;
4218 gfc_mark_ss_chain_used (lss, 1);
4219 }
4220 else
4221 {
4222 lse.ss = loop.temp_ss;
4223 gfc_mark_ss_chain_used (lss, 3);
4224 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4225 }
4226
4227 /* Start the scalarized loop body. */
4228 gfc_start_scalarized_body (&loop, &body);
4229
4230 /* Translate the expression. */
4231 gfc_conv_expr (&rse, expr2);
4232 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
3db5d687 4233 gfc_conv_tmp_array_ref (&lse);
6de9cd9a
DN
4234 else
4235 gfc_conv_expr (&lse, expr1);
4236
3c90c9ae 4237 /* Form the mask expression according to the mask. */
6de9cd9a 4238 index = count1;
1d6b7f39 4239 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76 4240 if (invert)
bc98ed60
TB
4241 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4242 TREE_TYPE (maskexpr), maskexpr);
6de9cd9a 4243
6de9cd9a 4244 /* Use the scalar assignment as is. */
eb74e79b 4245 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
2b56d6a4 4246 loop.temp_ss != NULL, false, true);
a00b8d1a 4247
c2255bc4 4248 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
6de9cd9a
DN
4249
4250 gfc_add_expr_to_block (&body, tmp);
4251
4252 if (lss == gfc_ss_terminator)
4253 {
4254 /* Increment count1. */
bc98ed60
TB
4255 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4256 count1, gfc_index_one_node);
726a989a 4257 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
4258
4259 /* Use the scalar assignment as is. */
4260 gfc_add_block_to_block (&block, &body);
4261 }
4262 else
4263 {
6e45f57b
PB
4264 gcc_assert (lse.ss == gfc_ss_terminator
4265 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
4266
4267 if (loop.temp_ss != NULL)
4268 {
4269 /* Increment count1 before finish the main body of a scalarized
4270 expression. */
bc98ed60
TB
4271 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4272 gfc_array_index_type, count1, gfc_index_one_node);
726a989a 4273 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
4274 gfc_trans_scalarized_loop_boundary (&loop, &body);
4275
4276 /* We need to copy the temporary to the actual lhs. */
4277 gfc_init_se (&lse, NULL);
4278 gfc_init_se (&rse, NULL);
4279 gfc_copy_loopinfo_to_se (&lse, &loop);
4280 gfc_copy_loopinfo_to_se (&rse, &loop);
4281
4282 rse.ss = loop.temp_ss;
4283 lse.ss = lss;
4284
4285 gfc_conv_tmp_array_ref (&rse);
6de9cd9a
DN
4286 gfc_conv_expr (&lse, expr1);
4287
6e45f57b
PB
4288 gcc_assert (lse.ss == gfc_ss_terminator
4289 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
4290
4291 /* Form the mask expression according to the mask tree list. */
4292 index = count2;
1d6b7f39 4293 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76 4294 if (invert)
bc98ed60
TB
4295 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4296 TREE_TYPE (maskexpr), maskexpr);
6de9cd9a 4297
6de9cd9a 4298 /* Use the scalar assignment as is. */
2b56d6a4
TB
4299 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4300 true);
c2255bc4
AH
4301 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4302 build_empty_stmt (input_location));
6de9cd9a 4303 gfc_add_expr_to_block (&body, tmp);
7ab92584 4304
6de9cd9a 4305 /* Increment count2. */
bc98ed60
TB
4306 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4307 gfc_array_index_type, count2,
4308 gfc_index_one_node);
726a989a 4309 gfc_add_modify (&body, count2, tmp);
6de9cd9a
DN
4310 }
4311 else
4312 {
4313 /* Increment count1. */
bc98ed60
TB
4314 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4315 gfc_array_index_type, count1,
4316 gfc_index_one_node);
726a989a 4317 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
4318 }
4319
4320 /* Generate the copying loops. */
4321 gfc_trans_scalarizing_loops (&loop, &body);
4322
4323 /* Wrap the whole thing up. */
4324 gfc_add_block_to_block (&block, &loop.pre);
4325 gfc_add_block_to_block (&block, &loop.post);
4326 gfc_cleanup_loop (&loop);
4327 }
4328
4329 return gfc_finish_block (&block);
4330}
4331
4332
4333/* Translate the WHERE construct or statement.
aa9c57ec 4334 This function can be called iteratively to translate the nested WHERE
6de9cd9a 4335 construct or statement.
3891cee2 4336 MASK is the control mask. */
6de9cd9a
DN
4337
4338static void
011daa76 4339gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
3891cee2 4340 forall_info * nested_forall_info, stmtblock_t * block)
6de9cd9a 4341{
3891cee2
RS
4342 stmtblock_t inner_size_body;
4343 tree inner_size, size;
4344 gfc_ss *lss, *rss;
4345 tree mask_type;
6de9cd9a
DN
4346 gfc_expr *expr1;
4347 gfc_expr *expr2;
4348 gfc_code *cblock;
4349 gfc_code *cnext;
3891cee2 4350 tree tmp;
ae772c2d 4351 tree cond;
6de9cd9a 4352 tree count1, count2;
011daa76
RS
4353 bool need_cmask;
4354 bool need_pmask;
6de9cd9a 4355 int need_temp;
3891cee2
RS
4356 tree pcmask = NULL_TREE;
4357 tree ppmask = NULL_TREE;
4358 tree cmask = NULL_TREE;
4359 tree pmask = NULL_TREE;
a00b8d1a 4360 gfc_actual_arglist *arg;
6de9cd9a
DN
4361
4362 /* the WHERE statement or the WHERE construct statement. */
4363 cblock = code->block;
3891cee2 4364
3891cee2
RS
4365 /* As the mask array can be very big, prefer compact boolean types. */
4366 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4367
011daa76
RS
4368 /* Determine which temporary masks are needed. */
4369 if (!cblock->block)
90f58ec8 4370 {
011daa76
RS
4371 /* One clause: No ELSEWHEREs. */
4372 need_cmask = (cblock->next != 0);
4373 need_pmask = false;
90f58ec8 4374 }
011daa76 4375 else if (cblock->block->block)
90f58ec8 4376 {
011daa76
RS
4377 /* Three or more clauses: Conditional ELSEWHEREs. */
4378 need_cmask = true;
4379 need_pmask = true;
90f58ec8 4380 }
011daa76
RS
4381 else if (cblock->next)
4382 {
4383 /* Two clauses, the first non-empty. */
4384 need_cmask = true;
4385 need_pmask = (mask != NULL_TREE
4386 && cblock->block->next != 0);
4387 }
4388 else if (!cblock->block->next)
3891cee2 4389 {
011daa76
RS
4390 /* Two clauses, both empty. */
4391 need_cmask = false;
4392 need_pmask = false;
4393 }
4394 /* Two clauses, the first empty, the second non-empty. */
4395 else if (mask)
4396 {
a513927a 4397 need_cmask = (cblock->block->expr1 != 0);
011daa76 4398 need_pmask = true;
3891cee2
RS
4399 }
4400 else
4401 {
011daa76
RS
4402 need_cmask = true;
4403 need_pmask = false;
4404 }
4405
4406 if (need_cmask || need_pmask)
4407 {
4408 /* Calculate the size of temporary needed by the mask-expr. */
4409 gfc_init_block (&inner_size_body);
a513927a 4410 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
011daa76
RS
4411 &inner_size_body, &lss, &rss);
4412
fcba5509
MM
4413 gfc_free_ss_chain (lss);
4414 gfc_free_ss_chain (rss);
4415
011daa76
RS
4416 /* Calculate the total size of temporary needed. */
4417 size = compute_overall_iter_number (nested_forall_info, inner_size,
4418 &inner_size_body, block);
4419
ae772c2d 4420 /* Check whether the size is negative. */
bc98ed60
TB
4421 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4422 gfc_index_zero_node);
4423 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4424 cond, gfc_index_zero_node, size);
ae772c2d
PT
4425 size = gfc_evaluate_now (size, block);
4426
011daa76
RS
4427 /* Allocate temporary for WHERE mask if needed. */
4428 if (need_cmask)
4429 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4430 &pcmask);
4431
4432 /* Allocate temporary for !mask if needed. */
4433 if (need_pmask)
4434 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4435 &ppmask);
3891cee2
RS
4436 }
4437
6de9cd9a
DN
4438 while (cblock)
4439 {
011daa76
RS
4440 /* Each time around this loop, the where clause is conditional
4441 on the value of mask and invert, which are updated at the
4442 bottom of the loop. */
4443
6de9cd9a 4444 /* Has mask-expr. */
a513927a 4445 if (cblock->expr1)
6de9cd9a 4446 {
90f58ec8
RS
4447 /* Ensure that the WHERE mask will be evaluated exactly once.
4448 If there are no statements in this WHERE/ELSEWHERE clause,
4449 then we don't need to update the control mask (cmask).
4450 If this is the last clause of the WHERE construct, then
3891cee2 4451 we don't need to update the pending control mask (pmask). */
011daa76 4452 if (mask)
a513927a 4453 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
011daa76
RS
4454 mask, invert,
4455 cblock->next ? cmask : NULL_TREE,
4456 cblock->block ? pmask : NULL_TREE,
4457 mask_type, block);
4458 else
a513927a 4459 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
011daa76
RS
4460 NULL_TREE, false,
4461 (cblock->next || cblock->block)
4462 ? cmask : NULL_TREE,
4463 NULL_TREE, mask_type, block);
6de9cd9a 4464
011daa76 4465 invert = false;
6de9cd9a 4466 }
90f58ec8 4467 /* It's a final elsewhere-stmt. No mask-expr is present. */
6de9cd9a 4468 else
3891cee2 4469 cmask = mask;
6de9cd9a 4470
011daa76
RS
4471 /* The body of this where clause are controlled by cmask with
4472 sense specified by invert. */
4473
6de9cd9a
DN
4474 /* Get the assignment statement of a WHERE statement, or the first
4475 statement in where-body-construct of a WHERE construct. */
4476 cnext = cblock->next;
4477 while (cnext)
4478 {
4479 switch (cnext->op)
4480 {
4481 /* WHERE assignment statement. */
a00b8d1a
PT
4482 case EXEC_ASSIGN_CALL:
4483
4484 arg = cnext->ext.actual;
4485 expr1 = expr2 = NULL;
4486 for (; arg; arg = arg->next)
4487 {
4488 if (!arg->expr)
4489 continue;
4490 if (expr1 == NULL)
4491 expr1 = arg->expr;
4492 else
4493 expr2 = arg->expr;
4494 }
4495 goto evaluate;
4496
6de9cd9a 4497 case EXEC_ASSIGN:
a513927a 4498 expr1 = cnext->expr1;
6de9cd9a 4499 expr2 = cnext->expr2;
a00b8d1a 4500 evaluate:
6de9cd9a
DN
4501 if (nested_forall_info != NULL)
4502 {
3ded6210 4503 need_temp = gfc_check_dependency (expr1, expr2, 0);
a00b8d1a 4504 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
011daa76
RS
4505 gfc_trans_assign_need_temp (expr1, expr2,
4506 cmask, invert,
6de9cd9a
DN
4507 nested_forall_info, block);
4508 else
4509 {
4510 /* Variables to control maskexpr. */
4511 count1 = gfc_create_var (gfc_array_index_type, "count1");
4512 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
4513 gfc_add_modify (block, count1, gfc_index_zero_node);
4514 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 4515
011daa76
RS
4516 tmp = gfc_trans_where_assign (expr1, expr2,
4517 cmask, invert,
a00b8d1a 4518 count1, count2,
eb74e79b 4519 cnext);
8de1f441 4520
6de9cd9a 4521 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
bfcabc6c 4522 tmp, 1);
6de9cd9a
DN
4523 gfc_add_expr_to_block (block, tmp);
4524 }
4525 }
4526 else
4527 {
4528 /* Variables to control maskexpr. */
4529 count1 = gfc_create_var (gfc_array_index_type, "count1");
4530 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
4531 gfc_add_modify (block, count1, gfc_index_zero_node);
4532 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 4533
011daa76
RS
4534 tmp = gfc_trans_where_assign (expr1, expr2,
4535 cmask, invert,
a00b8d1a 4536 count1, count2,
eb74e79b 4537 cnext);
6de9cd9a
DN
4538 gfc_add_expr_to_block (block, tmp);
4539
4540 }
4541 break;
4542
4543 /* WHERE or WHERE construct is part of a where-body-construct. */
4544 case EXEC_WHERE:
011daa76
RS
4545 gfc_trans_where_2 (cnext, cmask, invert,
4546 nested_forall_info, block);
3891cee2 4547 break;
6de9cd9a
DN
4548
4549 default:
6e45f57b 4550 gcc_unreachable ();
6de9cd9a
DN
4551 }
4552
4553 /* The next statement within the same where-body-construct. */
4554 cnext = cnext->next;
4555 }
4556 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4557 cblock = cblock->block;
011daa76
RS
4558 if (mask == NULL_TREE)
4559 {
4560 /* If we're the initial WHERE, we can simply invert the sense
4561 of the current mask to obtain the "mask" for the remaining
4562 ELSEWHEREs. */
4563 invert = true;
4564 mask = cmask;
4565 }
4566 else
4567 {
4568 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4569 invert = false;
4570 mask = pmask;
4571 }
6de9cd9a 4572 }
3891cee2
RS
4573
4574 /* If we allocated a pending mask array, deallocate it now. */
4575 if (ppmask)
4576 {
1529b8d9 4577 tmp = gfc_call_free (ppmask);
3891cee2
RS
4578 gfc_add_expr_to_block (block, tmp);
4579 }
4580
4581 /* If we allocated a current mask array, deallocate it now. */
4582 if (pcmask)
4583 {
1529b8d9 4584 tmp = gfc_call_free (pcmask);
3891cee2
RS
4585 gfc_add_expr_to_block (block, tmp);
4586 }
6de9cd9a
DN
4587}
4588
3ded6210
RS
4589/* Translate a simple WHERE construct or statement without dependencies.
4590 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4591 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4592 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4593
4594static tree
4595gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4596{
4597 stmtblock_t block, body;
4598 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4599 tree tmp, cexpr, tstmt, estmt;
4600 gfc_ss *css, *tdss, *tsss;
4601 gfc_se cse, tdse, tsse, edse, esse;
4602 gfc_loopinfo loop;
4603 gfc_ss *edss = 0;
4604 gfc_ss *esss = 0;
4605
34d01e1d
VL
4606 /* Allow the scalarizer to workshare simple where loops. */
4607 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4608 ompws_flags |= OMPWS_SCALARIZER_WS;
4609
a513927a
SK
4610 cond = cblock->expr1;
4611 tdst = cblock->next->expr1;
3ded6210 4612 tsrc = cblock->next->expr2;
a513927a 4613 edst = eblock ? eblock->next->expr1 : NULL;
3ded6210
RS
4614 esrc = eblock ? eblock->next->expr2 : NULL;
4615
4616 gfc_start_block (&block);
4617 gfc_init_loopinfo (&loop);
4618
4619 /* Handle the condition. */
4620 gfc_init_se (&cse, NULL);
4621 css = gfc_walk_expr (cond);
4622 gfc_add_ss_to_loop (&loop, css);
4623
4624 /* Handle the then-clause. */
4625 gfc_init_se (&tdse, NULL);
4626 gfc_init_se (&tsse, NULL);
4627 tdss = gfc_walk_expr (tdst);
4628 tsss = gfc_walk_expr (tsrc);
4629 if (tsss == gfc_ss_terminator)
4630 {
26f77530 4631 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
42d0058e 4632 tsss->info->where = 1;
3ded6210
RS
4633 }
4634 gfc_add_ss_to_loop (&loop, tdss);
4635 gfc_add_ss_to_loop (&loop, tsss);
4636
4637 if (eblock)
4638 {
4639 /* Handle the else clause. */
4640 gfc_init_se (&edse, NULL);
4641 gfc_init_se (&esse, NULL);
4642 edss = gfc_walk_expr (edst);
4643 esss = gfc_walk_expr (esrc);
4644 if (esss == gfc_ss_terminator)
4645 {
26f77530 4646 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
42d0058e 4647 esss->info->where = 1;
3ded6210
RS
4648 }
4649 gfc_add_ss_to_loop (&loop, edss);
4650 gfc_add_ss_to_loop (&loop, esss);
4651 }
4652
4653 gfc_conv_ss_startstride (&loop);
bdfd2ff0 4654 gfc_conv_loop_setup (&loop, &tdst->where);
3ded6210
RS
4655
4656 gfc_mark_ss_chain_used (css, 1);
4657 gfc_mark_ss_chain_used (tdss, 1);
4658 gfc_mark_ss_chain_used (tsss, 1);
4659 if (eblock)
4660 {
4661 gfc_mark_ss_chain_used (edss, 1);
4662 gfc_mark_ss_chain_used (esss, 1);
4663 }
4664
4665 gfc_start_scalarized_body (&loop, &body);
4666
4667 gfc_copy_loopinfo_to_se (&cse, &loop);
4668 gfc_copy_loopinfo_to_se (&tdse, &loop);
4669 gfc_copy_loopinfo_to_se (&tsse, &loop);
4670 cse.ss = css;
4671 tdse.ss = tdss;
4672 tsse.ss = tsss;
4673 if (eblock)
4674 {
4675 gfc_copy_loopinfo_to_se (&edse, &loop);
4676 gfc_copy_loopinfo_to_se (&esse, &loop);
4677 edse.ss = edss;
4678 esse.ss = esss;
4679 }
4680
4681 gfc_conv_expr (&cse, cond);
4682 gfc_add_block_to_block (&body, &cse.pre);
4683 cexpr = cse.expr;
4684
4685 gfc_conv_expr (&tsse, tsrc);
4686 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
3db5d687 4687 gfc_conv_tmp_array_ref (&tdse);
3ded6210
RS
4688 else
4689 gfc_conv_expr (&tdse, tdst);
4690
4691 if (eblock)
4692 {
4693 gfc_conv_expr (&esse, esrc);
4694 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
3db5d687 4695 gfc_conv_tmp_array_ref (&edse);
3ded6210 4696 else
3db5d687 4697 gfc_conv_expr (&edse, edst);
3ded6210
RS
4698 }
4699
2b56d6a4
TB
4700 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4701 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4702 false, true)
c2255bc4 4703 : build_empty_stmt (input_location);
3ded6210
RS
4704 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4705 gfc_add_expr_to_block (&body, tmp);
4706 gfc_add_block_to_block (&body, &cse.post);
4707
4708 gfc_trans_scalarizing_loops (&loop, &body);
4709 gfc_add_block_to_block (&block, &loop.pre);
4710 gfc_add_block_to_block (&block, &loop.post);
4711 gfc_cleanup_loop (&loop);
4712
4713 return gfc_finish_block (&block);
4714}
6de9cd9a
DN
4715
4716/* As the WHERE or WHERE construct statement can be nested, we call
4717 gfc_trans_where_2 to do the translation, and pass the initial
f7b529fa 4718 NULL values for both the control mask and the pending control mask. */
6de9cd9a
DN
4719
4720tree
4721gfc_trans_where (gfc_code * code)
4722{
4723 stmtblock_t block;
3ded6210
RS
4724 gfc_code *cblock;
4725 gfc_code *eblock;
6de9cd9a 4726
3ded6210
RS
4727 cblock = code->block;
4728 if (cblock->next
4729 && cblock->next->op == EXEC_ASSIGN
4730 && !cblock->next->next)
4731 {
4732 eblock = cblock->block;
4733 if (!eblock)
4734 {
4735 /* A simple "WHERE (cond) x = y" statement or block is
4736 dependence free if cond is not dependent upon writing x,
4737 and the source y is unaffected by the destination x. */
a513927a
SK
4738 if (!gfc_check_dependency (cblock->next->expr1,
4739 cblock->expr1, 0)
4740 && !gfc_check_dependency (cblock->next->expr1,
3ded6210
RS
4741 cblock->next->expr2, 0))
4742 return gfc_trans_where_3 (cblock, NULL);
4743 }
a513927a 4744 else if (!eblock->expr1
3ded6210
RS
4745 && !eblock->block
4746 && eblock->next
4747 && eblock->next->op == EXEC_ASSIGN
4748 && !eblock->next->next)
4749 {
4750 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4751 block is dependence free if cond is not dependent on writes
4752 to x1 and x2, y1 is not dependent on writes to x2, and y2
4753 is not dependent on writes to x1, and both y's are not
ae772c2d
PT
4754 dependent upon their own x's. In addition to this, the
4755 final two dependency checks below exclude all but the same
4756 array reference if the where and elswhere destinations
4757 are the same. In short, this is VERY conservative and this
4758 is needed because the two loops, required by the standard
4759 are coalesced in gfc_trans_where_3. */
524af0d6 4760 if (!gfc_check_dependency (cblock->next->expr1,
a513927a 4761 cblock->expr1, 0)
524af0d6 4762 && !gfc_check_dependency (eblock->next->expr1,
a513927a 4763 cblock->expr1, 0)
524af0d6 4764 && !gfc_check_dependency (cblock->next->expr1,
ae772c2d 4765 eblock->next->expr2, 1)
524af0d6 4766 && !gfc_check_dependency (eblock->next->expr1,
ae772c2d 4767 cblock->next->expr2, 1)
524af0d6 4768 && !gfc_check_dependency (cblock->next->expr1,
ae772c2d 4769 cblock->next->expr2, 1)
524af0d6 4770 && !gfc_check_dependency (eblock->next->expr1,
ae772c2d 4771 eblock->next->expr2, 1)
524af0d6 4772 && !gfc_check_dependency (cblock->next->expr1,
a513927a 4773 eblock->next->expr1, 0)
524af0d6 4774 && !gfc_check_dependency (eblock->next->expr1,
a513927a 4775 cblock->next->expr1, 0))
3ded6210
RS
4776 return gfc_trans_where_3 (cblock, eblock);
4777 }
4778 }
4779
6de9cd9a 4780 gfc_start_block (&block);
6de9cd9a 4781
011daa76 4782 gfc_trans_where_2 (code, NULL, false, NULL, &block);
6de9cd9a 4783
6de9cd9a
DN
4784 return gfc_finish_block (&block);
4785}
4786
4787
4788/* CYCLE a DO loop. The label decl has already been created by
4789 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4790 node at the head of the loop. We must mark the label as used. */
4791
4792tree
4793gfc_trans_cycle (gfc_code * code)
4794{
4795 tree cycle_label;
4796
e5ca9693
DK
4797 cycle_label = code->ext.which_construct->cycle_label;
4798 gcc_assert (cycle_label);
4799
6de9cd9a
DN
4800 TREE_USED (cycle_label) = 1;
4801 return build1_v (GOTO_EXPR, cycle_label);
4802}
4803
4804
e7dc5b4f 4805/* EXIT a DO loop. Similar to CYCLE, but now the label is in
6de9cd9a
DN
4806 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4807 loop. */
4808
4809tree
4810gfc_trans_exit (gfc_code * code)
4811{
4812 tree exit_label;
4813
e5ca9693
DK
4814 exit_label = code->ext.which_construct->exit_label;
4815 gcc_assert (exit_label);
4816
6de9cd9a
DN
4817 TREE_USED (exit_label) = 1;
4818 return build1_v (GOTO_EXPR, exit_label);
4819}
4820
4821
4822/* Translate the ALLOCATE statement. */
4823
4824tree
4825gfc_trans_allocate (gfc_code * code)
4826{
4827 gfc_alloc *al;
c49ea23d 4828 gfc_expr *e;
7adac79a 4829 gfc_expr *expr;
6de9cd9a
DN
4830 gfc_se se;
4831 tree tmp;
4832 tree parm;
6de9cd9a 4833 tree stat;
8f992d64
DC
4834 tree errmsg;
4835 tree errlen;
4836 tree label_errmsg;
4837 tree label_finish;
60f5ed26 4838 tree memsz;
90cf3ecc
PT
4839 tree expr3;
4840 tree slen3;
6de9cd9a 4841 stmtblock_t block;
90cf3ecc
PT
4842 stmtblock_t post;
4843 gfc_expr *sz;
4844 gfc_se se_sz;
4daa71b0
PT
4845 tree class_expr;
4846 tree nelems;
4847 tree memsize = NULL_TREE;
4848 tree classexpr = NULL_TREE;
6de9cd9a 4849
cf2b3c22 4850 if (!code->ext.alloc.list)
6de9cd9a
DN
4851 return NULL_TREE;
4852
8f992d64
DC
4853 stat = tmp = memsz = NULL_TREE;
4854 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
3759634f 4855
90cf3ecc
PT
4856 gfc_init_block (&block);
4857 gfc_init_block (&post);
6de9cd9a 4858
8f992d64
DC
4859 /* STAT= (and maybe ERRMSG=) is present. */
4860 if (code->expr1)
6de9cd9a 4861 {
8f992d64 4862 /* STAT=. */
e2cad04b 4863 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 4864 stat = gfc_create_var (gfc_int4_type_node, "stat");
6de9cd9a 4865
8f992d64
DC
4866 /* ERRMSG= only makes sense with STAT=. */
4867 if (code->expr2)
4868 {
4869 gfc_init_se (&se, NULL);
5d81ddd0 4870 se.want_pointer = 1;
8f992d64 4871 gfc_conv_expr_lhs (&se, code->expr2);
5d81ddd0
TB
4872 errmsg = se.expr;
4873 errlen = se.string_length;
8f992d64
DC
4874 }
4875 else
4876 {
4877 errmsg = null_pointer_node;
4878 errlen = build_int_cst (gfc_charlen_type_node, 0);
4879 }
4880
4881 /* GOTO destinations. */
4882 label_errmsg = gfc_build_label_decl (NULL_TREE);
4883 label_finish = gfc_build_label_decl (NULL_TREE);
5d81ddd0 4884 TREE_USED (label_finish) = 0;
6de9cd9a 4885 }
6de9cd9a 4886
90cf3ecc
PT
4887 expr3 = NULL_TREE;
4888 slen3 = NULL_TREE;
4889
cf2b3c22 4890 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6de9cd9a 4891 {
f43085aa
JW
4892 expr = gfc_copy_expr (al->expr);
4893
4894 if (expr->ts.type == BT_CLASS)
b04533af 4895 gfc_add_data_component (expr);
6de9cd9a
DN
4896
4897 gfc_init_se (&se, NULL);
6de9cd9a
DN
4898
4899 se.want_pointer = 1;
4900 se.descriptor_only = 1;
4901 gfc_conv_expr (&se, expr);
4902
4daa71b0
PT
4903 /* Evaluate expr3 just once if not a variable. */
4904 if (al == code->ext.alloc.list
4905 && al->expr->ts.type == BT_CLASS
4906 && code->expr3
4907 && code->expr3->ts.type == BT_CLASS
4908 && code->expr3->expr_type != EXPR_VARIABLE)
4909 {
4910 gfc_init_se (&se_sz, NULL);
4911 gfc_conv_expr_reference (&se_sz, code->expr3);
4912 gfc_conv_class_to_class (&se_sz, code->expr3,
16e82b25 4913 code->expr3->ts, false, true, false, false);
4daa71b0
PT
4914 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4915 gfc_add_block_to_block (&se.post, &se_sz.post);
4916 classexpr = build_fold_indirect_ref_loc (input_location,
4917 se_sz.expr);
4918 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4919 memsize = gfc_vtable_size_get (classexpr);
4920 memsize = fold_convert (sizetype, memsize);
4921 }
4922
4923 memsz = memsize;
4924 class_expr = classexpr;
4925
4926 nelems = NULL_TREE;
5d81ddd0 4927 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4daa71b0 4928 memsz, &nelems, code->expr3))
6de9cd9a 4929 {
8b704316
PT
4930 bool unlimited_char;
4931
4932 unlimited_char = UNLIMITED_POLY (al->expr)
4933 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
4934 || (code->ext.alloc.ts.type == BT_CHARACTER
4935 && code->ext.alloc.ts.u.cl
4936 && code->ext.alloc.ts.u.cl->length));
4937
6de9cd9a 4938 /* A scalar or derived type. */
cf2b3c22
TB
4939
4940 /* Determine allocate size. */
4daa71b0 4941 if (al->expr->ts.type == BT_CLASS
8b704316 4942 && !unlimited_char
4daa71b0
PT
4943 && code->expr3
4944 && memsz == NULL_TREE)
cf2b3c22 4945 {
94bff632
JW
4946 if (code->expr3->ts.type == BT_CLASS)
4947 {
94bff632 4948 sz = gfc_copy_expr (code->expr3);
b04533af
JW
4949 gfc_add_vptr_component (sz);
4950 gfc_add_size_component (sz);
94bff632
JW
4951 gfc_init_se (&se_sz, NULL);
4952 gfc_conv_expr (&se_sz, sz);
4953 gfc_free_expr (sz);
4954 memsz = se_sz.expr;
4955 }
4956 else
4957 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
cf2b3c22 4958 }
8b704316
PT
4959 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4960 || unlimited_char) && code->expr3)
8d51f26f
PT
4961 {
4962 if (!code->expr3->ts.u.cl->backend_decl)
4963 {
4964 /* Convert and use the length expression. */
8d51f26f
PT
4965 gfc_init_se (&se_sz, NULL);
4966 if (code->expr3->expr_type == EXPR_VARIABLE
4967 || code->expr3->expr_type == EXPR_CONSTANT)
4968 {
4969 gfc_conv_expr (&se_sz, code->expr3);
505920d6
SK
4970 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4971 se_sz.string_length
4972 = gfc_evaluate_now (se_sz.string_length, &se.pre);
4973 gfc_add_block_to_block (&se.pre, &se_sz.post);
8d51f26f
PT
4974 memsz = se_sz.string_length;
4975 }
90cf3ecc
PT
4976 else if (code->expr3->mold
4977 && code->expr3->ts.u.cl
fabb6f8e
PT
4978 && code->expr3->ts.u.cl->length)
4979 {
4980 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
4981 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4982 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4983 gfc_add_block_to_block (&se.pre, &se_sz.post);
4984 memsz = se_sz.expr;
4985 }
fabb6f8e
PT
4986 else
4987 {
90cf3ecc
PT
4988 /* This is would be inefficient and possibly could
4989 generate wrong code if the result were not stored
4990 in expr3/slen3. */
4991 if (slen3 == NULL_TREE)
4992 {
4993 gfc_conv_expr (&se_sz, code->expr3);
4994 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4995 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
4996 gfc_add_block_to_block (&post, &se_sz.post);
4997 slen3 = gfc_evaluate_now (se_sz.string_length,
4998 &se.pre);
4999 }
5000 memsz = slen3;
fabb6f8e 5001 }
8d51f26f
PT
5002 }
5003 else
5004 /* Otherwise use the stored string length. */
5005 memsz = code->expr3->ts.u.cl->backend_decl;
5006 tmp = al->expr->ts.u.cl->backend_decl;
5007
5008 /* Store the string length. */
5009 if (tmp && TREE_CODE (tmp) == VAR_DECL)
fabb6f8e 5010 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
8d51f26f
PT
5011 memsz));
5012
5013 /* Convert to size in bytes, using the character KIND. */
8b704316
PT
5014 if (unlimited_char)
5015 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5016 else
8d51f26f
PT
5017 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5018 tmp = TYPE_SIZE_UNIT (tmp);
5019 memsz = fold_build2_loc (input_location, MULT_EXPR,
5020 TREE_TYPE (tmp), tmp,
5021 fold_convert (TREE_TYPE (tmp), memsz));
5022 }
8b704316
PT
5023 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5024 || unlimited_char)
2573aab9
TB
5025 {
5026 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5027 gfc_init_se (&se_sz, NULL);
5028 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5029 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5030 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5031 gfc_add_block_to_block (&se.pre, &se_sz.post);
5032 /* Store the string length. */
5033 tmp = al->expr->ts.u.cl->backend_decl;
5034 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5035 se_sz.expr));
5036 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5037 tmp = TYPE_SIZE_UNIT (tmp);
5038 memsz = fold_build2_loc (input_location, MULT_EXPR,
5039 TREE_TYPE (tmp), tmp,
5040 fold_convert (TREE_TYPE (se_sz.expr),
5041 se_sz.expr));
5042 }
cf2b3c22 5043 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
60f5ed26 5044 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
4daa71b0 5045 else if (memsz == NULL_TREE)
60f5ed26 5046 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
c4bbc105 5047
60f5ed26 5048 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
8d51f26f 5049 {
fabb6f8e
PT
5050 memsz = se.string_length;
5051
8d51f26f
PT
5052 /* Convert to size in bytes, using the character KIND. */
5053 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5054 tmp = TYPE_SIZE_UNIT (tmp);
5055 memsz = fold_build2_loc (input_location, MULT_EXPR,
5056 TREE_TYPE (tmp), tmp,
5057 fold_convert (TREE_TYPE (tmp), memsz));
5058 }
90cf3ecc 5059
5b130807 5060 /* Allocate - for non-pointers with re-alloc checking. */
90cf3ecc 5061 if (gfc_expr_attr (expr).allocatable)
979d4598 5062 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5d81ddd0 5063 stat, errmsg, errlen, label_finish, expr);
90cf3ecc 5064 else
4f13e17f 5065 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
6de9cd9a 5066
3bfe6da9
TB
5067 if (al->expr->ts.type == BT_DERIVED
5068 && expr->ts.u.derived->attr.alloc_comp)
5046aff5 5069 {
db3927fb 5070 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
bc21d315 5071 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5046aff5
PT
5072 gfc_add_expr_to_block (&se.pre, tmp);
5073 }
83f42cad 5074 else if (al->expr->ts.type == BT_CLASS)
c49ea23d 5075 {
8b704316 5076 /* With class objects, it is best to play safe and null the
c49ea23d
PT
5077 memory because we cannot know if dynamic types have allocatable
5078 components or not. */
5079 tmp = build_call_expr_loc (input_location,
5080 builtin_decl_explicit (BUILT_IN_MEMSET),
5081 3, se.expr, integer_zero_node, memsz);
5082 gfc_add_expr_to_block (&se.pre, tmp);
5083 }
6de9cd9a
DN
5084 }
5085
90cf3ecc 5086 gfc_add_block_to_block (&block, &se.pre);
cf2b3c22 5087
8f992d64
DC
5088 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5089 if (code->expr1)
5090 {
5d81ddd0 5091 tmp = build1_v (GOTO_EXPR, label_errmsg);
8f992d64
DC
5092 parm = fold_build2_loc (input_location, NE_EXPR,
5093 boolean_type_node, stat,
5094 build_int_cst (TREE_TYPE (stat), 0));
5095 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5d81ddd0 5096 gfc_unlikely (parm), tmp,
8f992d64
DC
5097 build_empty_stmt (input_location));
5098 gfc_add_expr_to_block (&block, tmp);
5099 }
8b704316
PT
5100
5101 /* We need the vptr of CLASS objects to be initialized. */
c49ea23d
PT
5102 e = gfc_copy_expr (al->expr);
5103 if (e->ts.type == BT_CLASS)
5104 {
4daa71b0 5105 gfc_expr *lhs, *rhs;
c49ea23d
PT
5106 gfc_se lse;
5107
5108 lhs = gfc_expr_to_initialize (e);
5109 gfc_add_vptr_component (lhs);
4daa71b0
PT
5110
5111 if (class_expr != NULL_TREE)
5112 {
5113 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5114 gfc_init_se (&lse, NULL);
5115 lse.want_pointer = 1;
5116 gfc_conv_expr (&lse, lhs);
5117 tmp = gfc_class_vptr_get (class_expr);
5118 gfc_add_modify (&block, lse.expr,
5119 fold_convert (TREE_TYPE (lse.expr), tmp));
5120 }
5121 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
c49ea23d
PT
5122 {
5123 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5124 rhs = gfc_copy_expr (code->expr3);
5125 gfc_add_vptr_component (rhs);
5126 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5127 gfc_add_expr_to_block (&block, tmp);
5128 gfc_free_expr (rhs);
5129 rhs = gfc_expr_to_initialize (e);
5130 }
5131 else
5132 {
5133 /* VPTR is fixed at compile time. */
5134 gfc_symbol *vtab;
5135 gfc_typespec *ts;
5136 if (code->expr3)
5137 ts = &code->expr3->ts;
5138 else if (e->ts.type == BT_DERIVED)
5139 ts = &e->ts;
8b704316 5140 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
c49ea23d
PT
5141 ts = &code->ext.alloc.ts;
5142 else if (e->ts.type == BT_CLASS)
5143 ts = &CLASS_DATA (e)->ts;
5144 else
5145 ts = &e->ts;
5146
8b704316 5147 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
c49ea23d 5148 {
8b704316 5149 if (ts->type == BT_DERIVED)
c49ea23d 5150 vtab = gfc_find_derived_vtab (ts->u.derived);
8b704316
PT
5151 else
5152 vtab = gfc_find_intrinsic_vtab (ts);
c49ea23d
PT
5153 gcc_assert (vtab);
5154 gfc_init_se (&lse, NULL);
5155 lse.want_pointer = 1;
5156 gfc_conv_expr (&lse, lhs);
5157 tmp = gfc_build_addr_expr (NULL_TREE,
5158 gfc_get_symbol_decl (vtab));
5159 gfc_add_modify (&block, lse.expr,
5160 fold_convert (TREE_TYPE (lse.expr), tmp));
5161 }
5162 }
5163 gfc_free_expr (lhs);
5164 }
5165
5166 gfc_free_expr (e);
5167
94bff632 5168 if (code->expr3 && !code->expr3->mold)
cf2b3c22 5169 {
b6ff8128
JW
5170 /* Initialization via SOURCE block
5171 (or static default initializer). */
f43085aa 5172 gfc_expr *rhs = gfc_copy_expr (code->expr3);
4daa71b0
PT
5173 if (class_expr != NULL_TREE)
5174 {
5175 tree to;
5176 to = TREE_OPERAND (se.expr, 0);
5177
5178 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5179 }
5180 else if (al->expr->ts.type == BT_CLASS)
f43085aa 5181 {
611c64f0
JW
5182 gfc_actual_arglist *actual;
5183 gfc_expr *ppc;
c49ea23d 5184 gfc_code *ppc_code;
e87924ab 5185 gfc_ref *ref, *dataref;
c49ea23d 5186
611c64f0
JW
5187 /* Do a polymorphic deep copy. */
5188 actual = gfc_get_actual_arglist ();
5189 actual->expr = gfc_copy_expr (rhs);
60f5ed26 5190 if (rhs->ts.type == BT_CLASS)
b04533af 5191 gfc_add_data_component (actual->expr);
611c64f0
JW
5192 actual->next = gfc_get_actual_arglist ();
5193 actual->next->expr = gfc_copy_expr (al->expr);
c49ea23d 5194 actual->next->expr->ts.type = BT_CLASS;
b04533af 5195 gfc_add_data_component (actual->next->expr);
83f42cad 5196
e87924ab 5197 dataref = NULL;
83f42cad
PT
5198 /* Make sure we go up through the reference chain to
5199 the _data reference, where the arrayspec is found. */
e87924ab
JW
5200 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5201 if (ref->type == REF_COMPONENT
5202 && strcmp (ref->u.c.component->name, "_data") == 0)
5203 dataref = ref;
83f42cad 5204
e87924ab 5205 if (dataref && dataref->u.c.component->as)
c49ea23d
PT
5206 {
5207 int dim;
5208 gfc_expr *temp;
5209 gfc_ref *ref = dataref->next;
5210 ref->u.ar.type = AR_SECTION;
5211 /* We have to set up the array reference to give ranges
5212 in all dimensions and ensure that the end and stride
5213 are set so that the copy can be scalarized. */
5214 dim = 0;
5215 for (; dim < dataref->u.c.component->as->rank; dim++)
5216 {
5217 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5218 if (ref->u.ar.end[dim] == NULL)
5219 {
5220 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5221 temp = gfc_get_int_expr (gfc_default_integer_kind,
5222 &al->expr->where, 1);
5223 ref->u.ar.start[dim] = temp;
5224 }
5225 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5226 gfc_copy_expr (ref->u.ar.start[dim]));
5227 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5228 &al->expr->where, 1),
5229 temp);
5230 }
5231 }
611c64f0
JW
5232 if (rhs->ts.type == BT_CLASS)
5233 {
5234 ppc = gfc_copy_expr (rhs);
b04533af 5235 gfc_add_vptr_component (ppc);
611c64f0 5236 }
8b704316 5237 else if (rhs->ts.type == BT_DERIVED)
c49ea23d
PT
5238 ppc = gfc_lval_expr_from_sym
5239 (gfc_find_derived_vtab (rhs->ts.u.derived));
8b704316
PT
5240 else
5241 ppc = gfc_lval_expr_from_sym
5242 (gfc_find_intrinsic_vtab (&rhs->ts));
b04533af 5243 gfc_add_component_ref (ppc, "_copy");
c49ea23d
PT
5244
5245 ppc_code = gfc_get_code ();
5246 ppc_code->resolved_sym = ppc->symtree->n.sym;
5247 /* Although '_copy' is set to be elemental in class.c, it is
5248 not staying that way. Find out why, sometime.... */
5249 ppc_code->resolved_sym->attr.elemental = 1;
5250 ppc_code->ext.actual = actual;
5251 ppc_code->expr1 = ppc;
5252 ppc_code->op = EXEC_CALL;
5253 /* Since '_copy' is elemental, the scalarizer will take care
5254 of arrays in gfc_trans_call. */
5255 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5256 gfc_free_statements (ppc_code);
f43085aa 5257 }
90cf3ecc
PT
5258 else if (expr3 != NULL_TREE)
5259 {
5260 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5261 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5262 slen3, expr3, code->expr3->ts.kind);
5263 tmp = NULL_TREE;
5264 }
f43085aa 5265 else
fabb6f8e
PT
5266 {
5267 /* Switch off automatic reallocation since we have just done
5268 the ALLOCATE. */
5269 int realloc_lhs = gfc_option.flag_realloc_lhs;
5270 gfc_option.flag_realloc_lhs = 0;
5271 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5272 rhs, false, false);
5273 gfc_option.flag_realloc_lhs = realloc_lhs;
5274 }
f43085aa
JW
5275 gfc_free_expr (rhs);
5276 gfc_add_expr_to_block (&block, tmp);
5277 }
4daa71b0 5278 else if (code->expr3 && code->expr3->mold
b6ff8128 5279 && code->expr3->ts.type == BT_CLASS)
50f30801 5280 {
4daa71b0
PT
5281 /* Since the _vptr has already been assigned to the allocate
5282 object, we can use gfc_copy_class_to_class in its
5283 initialization mode. */
5284 tmp = TREE_OPERAND (se.expr, 0);
5285 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
b6ff8128 5286 gfc_add_expr_to_block (&block, tmp);
50f30801 5287 }
f43085aa 5288
4daa71b0 5289 gfc_free_expr (expr);
6de9cd9a
DN
5290 }
5291
5d81ddd0 5292 /* STAT. */
a513927a 5293 if (code->expr1)
6de9cd9a 5294 {
8f992d64 5295 tmp = build1_v (LABEL_EXPR, label_errmsg);
6de9cd9a 5296 gfc_add_expr_to_block (&block, tmp);
6de9cd9a
DN
5297 }
5298
5d81ddd0
TB
5299 /* ERRMSG - only useful if STAT is present. */
5300 if (code->expr1 && code->expr2)
3759634f 5301 {
3759634f 5302 const char *msg = "Attempt to allocate an allocated object";
5d81ddd0
TB
5303 tree slen, dlen, errmsg_str;
5304 stmtblock_t errmsg_block;
3759634f 5305
5d81ddd0 5306 gfc_init_block (&errmsg_block);
3759634f 5307
5d81ddd0
TB
5308 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5309 gfc_add_modify (&errmsg_block, errmsg_str,
3759634f
SK
5310 gfc_build_addr_expr (pchar_type_node,
5311 gfc_build_localized_cstring_const (msg)));
5312
5313 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5314 dlen = gfc_get_expr_charlen (code->expr2);
bc98ed60
TB
5315 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5316 slen);
3759634f 5317
5d81ddd0
TB
5318 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5319 slen, errmsg_str, gfc_default_character_kind);
5320 dlen = gfc_finish_block (&errmsg_block);
3759634f 5321
bc98ed60
TB
5322 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5323 build_int_cst (TREE_TYPE (stat), 0));
3759634f 5324
c2255bc4 5325 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
3759634f
SK
5326
5327 gfc_add_expr_to_block (&block, tmp);
5328 }
5329
8f992d64
DC
5330 /* STAT block. */
5331 if (code->expr1)
5332 {
5d81ddd0
TB
5333 if (TREE_USED (label_finish))
5334 {
5335 tmp = build1_v (LABEL_EXPR, label_finish);
5336 gfc_add_expr_to_block (&block, tmp);
5337 }
5338
8f992d64
DC
5339 gfc_init_se (&se, NULL);
5340 gfc_conv_expr_lhs (&se, code->expr1);
5341 tmp = convert (TREE_TYPE (se.expr), stat);
5342 gfc_add_modify (&block, se.expr, tmp);
5343 }
5344
90cf3ecc
PT
5345 gfc_add_block_to_block (&block, &se.post);
5346 gfc_add_block_to_block (&block, &post);
5347
6de9cd9a
DN
5348 return gfc_finish_block (&block);
5349}
5350
5351
8b704316
PT
5352/* Reset the vptr after deallocation. */
5353
5354static void
5355reset_vptr (stmtblock_t *block, gfc_expr *e)
5356{
5357 gfc_expr *rhs, *lhs = gfc_copy_expr (e);
5358 gfc_symbol *vtab;
5359 tree tmp;
5360
5361 if (UNLIMITED_POLY (e))
5362 rhs = gfc_get_null_expr (NULL);
5363 else
5364 {
5365 vtab = gfc_find_derived_vtab (e->ts.u.derived);
5366 rhs = gfc_lval_expr_from_sym (vtab);
5367 }
5368 gfc_add_vptr_component (lhs);
5369 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5370 gfc_add_expr_to_block (block, tmp);
5371 gfc_free_expr (lhs);
5372 gfc_free_expr (rhs);
5373}
5374
5375
3759634f
SK
5376/* Translate a DEALLOCATE statement. */
5377
6de9cd9a 5378tree
3759634f 5379gfc_trans_deallocate (gfc_code *code)
6de9cd9a
DN
5380{
5381 gfc_se se;
5382 gfc_alloc *al;
5d81ddd0
TB
5383 tree apstat, pstat, stat, errmsg, errlen, tmp;
5384 tree label_finish, label_errmsg;
6de9cd9a
DN
5385 stmtblock_t block;
5386
5d81ddd0
TB
5387 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5388 label_finish = label_errmsg = NULL_TREE;
3759634f 5389
6de9cd9a
DN
5390 gfc_start_block (&block);
5391
3759634f
SK
5392 /* Count the number of failed deallocations. If deallocate() was
5393 called with STAT= , then set STAT to the count. If deallocate
5394 was called with ERRMSG, then set ERRMG to a string. */
5d81ddd0 5395 if (code->expr1)
364667a1
SK
5396 {
5397 tree gfc_int4_type_node = gfc_get_int_type (4);
5398
364667a1 5399 stat = gfc_create_var (gfc_int4_type_node, "stat");
628c189e 5400 pstat = gfc_build_addr_expr (NULL_TREE, stat);
364667a1 5401
5d81ddd0
TB
5402 /* GOTO destinations. */
5403 label_errmsg = gfc_build_label_decl (NULL_TREE);
5404 label_finish = gfc_build_label_decl (NULL_TREE);
5405 TREE_USED (label_finish) = 0;
5406 }
364667a1 5407
5d81ddd0
TB
5408 /* Set ERRMSG - only needed if STAT is available. */
5409 if (code->expr1 && code->expr2)
5410 {
5411 gfc_init_se (&se, NULL);
5412 se.want_pointer = 1;
5413 gfc_conv_expr_lhs (&se, code->expr2);
5414 errmsg = se.expr;
5415 errlen = se.string_length;
364667a1 5416 }
364667a1 5417
cf2b3c22 5418 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6de9cd9a 5419 {
0d87fa8c 5420 gfc_expr *expr = gfc_copy_expr (al->expr);
6e45f57b 5421 gcc_assert (expr->expr_type == EXPR_VARIABLE);
6de9cd9a 5422
0d87fa8c
JW
5423 if (expr->ts.type == BT_CLASS)
5424 gfc_add_data_component (expr);
5425
6de9cd9a
DN
5426 gfc_init_se (&se, NULL);
5427 gfc_start_block (&se.pre);
5428
5429 se.want_pointer = 1;
5430 se.descriptor_only = 1;
5431 gfc_conv_expr (&se, expr);
5432
5d81ddd0 5433 if (expr->rank || gfc_is_coarray (expr))
2c807128
JW
5434 {
5435 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
5046aff5 5436 {
2c807128
JW
5437 gfc_ref *ref;
5438 gfc_ref *last = NULL;
5439 for (ref = expr->ref; ref; ref = ref->next)
5440 if (ref->type == REF_COMPONENT)
5441 last = ref;
5442
5443 /* Do not deallocate the components of a derived type
5444 ultimate pointer component. */
5445 if (!(last && last->u.c.component->attr.pointer)
5446 && !(!last && expr->symtree->n.sym->attr.pointer))
5447 {
5448 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5449 expr->rank);
5450 gfc_add_expr_to_block (&se.pre, tmp);
5451 }
5046aff5 5452 }
5d81ddd0
TB
5453 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5454 label_finish, expr);
0d87fa8c 5455 gfc_add_expr_to_block (&se.pre, tmp);
8b704316
PT
5456 if (UNLIMITED_POLY (al->expr))
5457 reset_vptr (&se.pre, al->expr);
5046aff5 5458 }
6de9cd9a
DN
5459 else
5460 {
2c807128 5461 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
c5c1aeb2 5462 al->expr, al->expr->ts);
54200abb
RG
5463 gfc_add_expr_to_block (&se.pre, tmp);
5464
0d87fa8c 5465 /* Set to zero after deallocation. */
bc98ed60
TB
5466 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5467 se.expr,
5468 build_int_cst (TREE_TYPE (se.expr), 0));
0d87fa8c 5469 gfc_add_expr_to_block (&se.pre, tmp);
8b704316 5470
0d87fa8c 5471 if (al->expr->ts.type == BT_CLASS)
8b704316 5472 reset_vptr (&se.pre, al->expr);
6de9cd9a 5473 }
364667a1 5474
5d81ddd0 5475 if (code->expr1)
364667a1 5476 {
5d81ddd0
TB
5477 tree cond;
5478
5479 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5480 build_int_cst (TREE_TYPE (stat), 0));
5481 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5482 gfc_unlikely (cond),
5483 build1_v (GOTO_EXPR, label_errmsg),
5484 build_empty_stmt (input_location));
5485 gfc_add_expr_to_block (&se.pre, tmp);
364667a1
SK
5486 }
5487
6de9cd9a
DN
5488 tmp = gfc_finish_block (&se.pre);
5489 gfc_add_expr_to_block (&block, tmp);
0d87fa8c 5490 gfc_free_expr (expr);
364667a1
SK
5491 }
5492
a513927a 5493 if (code->expr1)
364667a1 5494 {
5d81ddd0
TB
5495 tmp = build1_v (LABEL_EXPR, label_errmsg);
5496 gfc_add_expr_to_block (&block, tmp);
6de9cd9a
DN
5497 }
5498
5d81ddd0
TB
5499 /* Set ERRMSG - only needed if STAT is available. */
5500 if (code->expr1 && code->expr2)
3759634f 5501 {
3759634f 5502 const char *msg = "Attempt to deallocate an unallocated object";
5d81ddd0
TB
5503 stmtblock_t errmsg_block;
5504 tree errmsg_str, slen, dlen, cond;
3759634f 5505
5d81ddd0 5506 gfc_init_block (&errmsg_block);
3759634f 5507
5d81ddd0
TB
5508 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5509 gfc_add_modify (&errmsg_block, errmsg_str,
3759634f
SK
5510 gfc_build_addr_expr (pchar_type_node,
5511 gfc_build_localized_cstring_const (msg)));
3759634f
SK
5512 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5513 dlen = gfc_get_expr_charlen (code->expr2);
3759634f 5514
5d81ddd0
TB
5515 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5516 slen, errmsg_str, gfc_default_character_kind);
5517 tmp = gfc_finish_block (&errmsg_block);
3759634f 5518
5d81ddd0
TB
5519 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5520 build_int_cst (TREE_TYPE (stat), 0));
5521 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5522 gfc_unlikely (cond), tmp,
5523 build_empty_stmt (input_location));
3759634f 5524
5d81ddd0
TB
5525 gfc_add_expr_to_block (&block, tmp);
5526 }
3759634f 5527
5d81ddd0
TB
5528 if (code->expr1 && TREE_USED (label_finish))
5529 {
5530 tmp = build1_v (LABEL_EXPR, label_finish);
3759634f
SK
5531 gfc_add_expr_to_block (&block, tmp);
5532 }
5533
5d81ddd0
TB
5534 /* Set STAT. */
5535 if (code->expr1)
5536 {
5537 gfc_init_se (&se, NULL);
5538 gfc_conv_expr_lhs (&se, code->expr1);
5539 tmp = convert (TREE_TYPE (se.expr), stat);
5540 gfc_add_modify (&block, se.expr, tmp);
5541 }
5542
6de9cd9a
DN
5543 return gfc_finish_block (&block);
5544}
5545
d2886bc7 5546#include "gt-fortran-trans-stmt.h"