]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-stmt.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / fortran / trans-stmt.cc
CommitLineData
6de9cd9a 1/* Statement translation -- generate GCC trees from gfc_code.
83ffe9cd 2 Copyright (C) 2002-2023 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"
c7131fb2 26#include "options.h"
2adfab87 27#include "tree.h"
6de9cd9a
DN
28#include "gfortran.h"
29#include "trans.h"
2adfab87 30#include "stringpool.h"
2adfab87 31#include "fold-const.h"
6de9cd9a
DN
32#include "trans-stmt.h"
33#include "trans-types.h"
34#include "trans-array.h"
35#include "trans-const.h"
3ded6210 36#include "dependency.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;
2ca4e2c2 56 bool do_concurrent;
6de9cd9a
DN
57}
58forall_info;
59
011daa76
RS
60static void gfc_trans_where_2 (gfc_code *, tree, bool,
61 forall_info *, stmtblock_t *);
6de9cd9a
DN
62
63/* Translate a F95 label number to a LABEL_EXPR. */
64
65tree
66gfc_trans_label_here (gfc_code * code)
67{
68 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
69}
70
ce2df7c6
FW
71
72/* Given a variable expression which has been ASSIGNed to, find the decl
73 containing the auxiliary variables. For variables in common blocks this
74 is a field_decl. */
75
76void
77gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
78{
79 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
80 gfc_conv_expr (se, expr);
81 /* Deals with variable in common block. Get the field declaration. */
82 if (TREE_CODE (se->expr) == COMPONENT_REF)
83 se->expr = TREE_OPERAND (se->expr, 1);
910450c1
FW
84 /* Deals with dummy argument. Get the parameter declaration. */
85 else if (TREE_CODE (se->expr) == INDIRECT_REF)
86 se->expr = TREE_OPERAND (se->expr, 0);
ce2df7c6
FW
87}
88
6de9cd9a 89/* Translate a label assignment statement. */
ce2df7c6 90
6de9cd9a
DN
91tree
92gfc_trans_label_assign (gfc_code * code)
93{
94 tree label_tree;
95 gfc_se se;
96 tree len;
97 tree addr;
98 tree len_tree;
6de9cd9a
DN
99 int label_len;
100
101 /* Start a new block. */
102 gfc_init_se (&se, NULL);
103 gfc_start_block (&se.pre);
a513927a 104 gfc_conv_label_variable (&se, code->expr1);
ce2df7c6 105
6de9cd9a
DN
106 len = GFC_DECL_STRING_LEN (se.expr);
107 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
108
79bd1948 109 label_tree = gfc_get_label_decl (code->label1);
6de9cd9a 110
f3e7b9d6
TB
111 if (code->label1->defined == ST_LABEL_TARGET
112 || code->label1->defined == ST_LABEL_DO_TARGET)
6de9cd9a
DN
113 {
114 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
f622221a 115 len_tree = build_int_cst (gfc_charlen_type_node, -1);
6de9cd9a
DN
116 }
117 else
118 {
79bd1948 119 gfc_expr *format = code->label1->format;
d393bbd7
FXC
120
121 label_len = format->value.character.length;
df09d1d5 122 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
d393bbd7
FXC
123 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
124 format->value.character.string);
b078dfbf 125 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
6de9cd9a
DN
126 }
127
f622221a 128 gfc_add_modify (&se.pre, len, fold_convert (TREE_TYPE (len), len_tree));
726a989a 129 gfc_add_modify (&se.pre, addr, label_tree);
6de9cd9a
DN
130
131 return gfc_finish_block (&se.pre);
132}
133
134/* Translate a GOTO statement. */
135
136tree
137gfc_trans_goto (gfc_code * code)
138{
dd18a33b 139 locus loc = code->loc;
6de9cd9a
DN
140 tree assigned_goto;
141 tree target;
142 tree tmp;
6de9cd9a
DN
143 gfc_se se;
144
79bd1948
SK
145 if (code->label1 != NULL)
146 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
6de9cd9a
DN
147
148 /* ASSIGNED GOTO. */
149 gfc_init_se (&se, NULL);
150 gfc_start_block (&se.pre);
a513927a 151 gfc_conv_label_variable (&se, code->expr1);
6de9cd9a 152 tmp = GFC_DECL_STRING_LEN (se.expr);
63ee5404 153 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
bc98ed60 154 build_int_cst (TREE_TYPE (tmp), -1));
0d52899f 155 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
c8fe94c7 156 "Assigned label is not a target label");
6de9cd9a
DN
157
158 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
6de9cd9a 159
916bd5f0
DK
160 /* We're going to ignore a label list. It does not really change the
161 statement's semantics (because it is just a further restriction on
162 what's legal code); before, we were comparing label addresses here, but
163 that's a very fragile business and may break with optimization. So
164 just ignore it. */
165
bc98ed60
TB
166 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
167 assigned_goto);
916bd5f0
DK
168 gfc_add_expr_to_block (&se.pre, target);
169 return gfc_finish_block (&se.pre);
6de9cd9a
DN
170}
171
172
3d79abbd
PB
173/* Translate an ENTRY statement. Just adds a label for this entry point. */
174tree
175gfc_trans_entry (gfc_code * code)
176{
177 return build1_v (LABEL_EXPR, code->ext.entry->label);
178}
179
180
fafcf9e6
MM
181/* Replace a gfc_ss structure by another both in the gfc_se struct
182 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
183 to replace a variable ss by the corresponding temporary. */
184
185static void
186replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
187{
188 gfc_ss **sess, **loopss;
189
190 /* The old_ss is a ss for a single variable. */
191 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
192
193 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
194 if (*sess == old_ss)
195 break;
196 gcc_assert (*sess != gfc_ss_terminator);
197
198 *sess = new_ss;
199 new_ss->next = old_ss->next;
200
5c5ce609
HA
201 /* Make sure that trailing references are not lost. */
202 if (old_ss->info
203 && old_ss->info->data.array.ref
204 && old_ss->info->data.array.ref->next
205 && !(new_ss->info->data.array.ref
206 && new_ss->info->data.array.ref->next))
207 new_ss->info->data.array.ref = old_ss->info->data.array.ref;
fafcf9e6
MM
208
209 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
210 loopss = &((*loopss)->loop_chain))
211 if (*loopss == old_ss)
212 break;
213 gcc_assert (*loopss != gfc_ss_terminator);
214
215 *loopss = new_ss;
216 new_ss->loop_chain = old_ss->loop_chain;
217 new_ss->loop = old_ss->loop;
218
219 gfc_free_ss (old_ss);
220}
221
222
476220e7
PT
223/* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
224 elemental subroutines. Make temporaries for output arguments if any such
225 dependencies are found. Output arguments are chosen because internal_unpack
226 can be used, as is, to copy the result back to the variable. */
227static void
228gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
2b0bd714
MM
229 gfc_symbol * sym, gfc_actual_arglist * arg,
230 gfc_dep_check check_variable)
476220e7
PT
231{
232 gfc_actual_arglist *arg0;
233 gfc_expr *e;
234 gfc_formal_arglist *formal;
476220e7
PT
235 gfc_se parmse;
236 gfc_ss *ss;
476220e7 237 gfc_symbol *fsym;
476220e7 238 tree data;
476220e7
PT
239 tree size;
240 tree tmp;
241
242 if (loopse->ss == NULL)
243 return;
244
245 ss = loopse->ss;
246 arg0 = arg;
4cbc9039 247 formal = gfc_sym_get_dummy_args (sym);
476220e7
PT
248
249 /* Loop over all the arguments testing for dependencies. */
250 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
251 {
252 e = arg->expr;
253 if (e == NULL)
254 continue;
255
8b704316 256 /* Obtain the info structure for the current argument. */
476220e7 257 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
fafcf9e6 258 if (ss->info->expr == e)
476220e7 259 break;
476220e7
PT
260
261 /* If there is a dependency, create a temporary and use it
66e4ab31 262 instead of the variable. */
476220e7
PT
263 fsym = formal ? formal->sym : NULL;
264 if (e->expr_type == EXPR_VARIABLE
265 && e->rank && fsym
06bcd751 266 && fsym->attr.intent != INTENT_IN
07b9bcc1 267 && !fsym->attr.value
06bcd751 268 && gfc_check_fncall_dependency (e, fsym->attr.intent,
2b0bd714 269 sym, arg0, check_variable))
476220e7 270 {
79e5286c 271 tree initial, temptype;
12f681a0 272 stmtblock_t temp_post;
fafcf9e6 273 gfc_ss *tmp_ss;
12f681a0 274
fafcf9e6
MM
275 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
276 GFC_SS_SECTION);
277 gfc_mark_ss_chain_used (tmp_ss, 1);
278 tmp_ss->info->expr = ss->info->expr;
279 replace_ss (loopse, ss, tmp_ss);
476220e7 280
12f681a0
DK
281 /* Obtain the argument descriptor for unpacking. */
282 gfc_init_se (&parmse, NULL);
283 parmse.want_pointer = 1;
2960a368 284 gfc_conv_expr_descriptor (&parmse, e);
12f681a0
DK
285 gfc_add_block_to_block (&se->pre, &parmse.pre);
286
eb74e79b
PT
287 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
288 initialize the array temporary with a copy of the values. */
289 if (fsym->attr.intent == INTENT_INOUT
290 || (fsym->ts.type ==BT_DERIVED
291 && fsym->attr.intent == INTENT_OUT))
12f681a0 292 initial = parmse.expr;
866e6d1b
PT
293 /* For class expressions, we always initialize with the copy of
294 the values. */
295 else if (e->ts.type == BT_CLASS)
296 initial = parmse.expr;
12f681a0
DK
297 else
298 initial = NULL_TREE;
299
866e6d1b
PT
300 if (e->ts.type != BT_CLASS)
301 {
302 /* Find the type of the temporary to create; we don't use the type
303 of e itself as this breaks for subcomponent-references in e
304 (where the type of e is that of the final reference, but
305 parmse.expr's type corresponds to the full derived-type). */
306 /* TODO: Fix this somehow so we don't need a temporary of the whole
307 array but instead only the components referenced. */
308 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
309 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
310 temptype = TREE_TYPE (temptype);
311 temptype = gfc_get_element_type (temptype);
312 }
313
314 else
315 /* For class arrays signal that the size of the dynamic type has to
316 be obtained from the vtable, using the 'initial' expression. */
317 temptype = NULL_TREE;
79e5286c
DK
318
319 /* Generate the temporary. Cleaning up the temporary should be the
320 very last thing done, so we add the code to a new block and add it
321 to se->post as last instructions. */
476220e7
PT
322 size = gfc_create_var (gfc_array_index_type, NULL);
323 data = gfc_create_var (pvoid_type_node, NULL);
12f681a0 324 gfc_init_block (&temp_post);
fafcf9e6 325 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
41645793
MM
326 temptype, initial, false, true,
327 false, &arg->expr->where);
726a989a 328 gfc_add_modify (&se->pre, size, tmp);
fafcf9e6 329 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
726a989a 330 gfc_add_modify (&se->pre, data, tmp);
476220e7 331
fafcf9e6
MM
332 /* Update other ss' delta. */
333 gfc_set_delta (loopse->loop);
476220e7 334
866e6d1b
PT
335 /* Copy the result back using unpack..... */
336 if (e->ts.type != BT_CLASS)
337 tmp = build_call_expr_loc (input_location,
338 gfor_fndecl_in_unpack, 2, parmse.expr, data);
339 else
340 {
341 /* ... except for class results where the copy is
342 unconditional. */
343 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
344 tmp = gfc_conv_descriptor_data_get (tmp);
345 tmp = build_call_expr_loc (input_location,
346 builtin_decl_explicit (BUILT_IN_MEMCPY),
ee4b6b52
JJ
347 3, tmp, data,
348 fold_convert (size_type_node, size));
866e6d1b 349 }
476220e7
PT
350 gfc_add_expr_to_block (&se->post, tmp);
351
79e5286c 352 /* parmse.pre is already added above. */
476220e7 353 gfc_add_block_to_block (&se->post, &parmse.post);
12f681a0 354 gfc_add_block_to_block (&se->post, &temp_post);
476220e7
PT
355 }
356 }
357}
358
359
68d62cb2
MM
360/* Given an executable statement referring to an intrinsic function call,
361 returns the intrinsic symbol. */
362
363static gfc_intrinsic_sym *
364get_intrinsic_for_code (gfc_code *code)
365{
366 if (code->op == EXEC_CALL)
367 {
368 gfc_intrinsic_sym * const isym = code->resolved_isym;
369 if (isym)
370 return isym;
371 else
372 return gfc_get_intrinsic_for_expr (code->expr1);
373 }
374
375 return NULL;
376}
377
378
6de9cd9a
DN
379/* Translate the CALL statement. Builds a call to an F95 subroutine. */
380
381tree
eb74e79b
PT
382gfc_trans_call (gfc_code * code, bool dependency_check,
383 tree mask, tree count1, bool invert)
6de9cd9a
DN
384{
385 gfc_se se;
48474141 386 gfc_ss * ss;
dda895f9 387 int has_alternate_specifier;
2b0bd714 388 gfc_dep_check check_variable;
eb74e79b
PT
389 tree index = NULL_TREE;
390 tree maskexpr = NULL_TREE;
391 tree tmp;
5c5ce609 392 bool is_intrinsic_mvbits;
6de9cd9a
DN
393
394 /* A CALL starts a new block because the actual arguments may have to
395 be evaluated first. */
396 gfc_init_se (&se, NULL);
397 gfc_start_block (&se.pre);
398
6e45f57b 399 gcc_assert (code->resolved_sym);
6de9cd9a 400
48474141
PT
401 ss = gfc_ss_terminator;
402 if (code->resolved_sym->attr.elemental)
17d038cd 403 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
68d62cb2 404 get_intrinsic_for_code (code),
dec131b6 405 GFC_SS_REFERENCE);
6de9cd9a 406
5c5ce609
HA
407 /* MVBITS is inlined but needs the dependency checking found here. */
408 is_intrinsic_mvbits = code->resolved_isym
409 && code->resolved_isym->id == GFC_ISYM_MVBITS;
410
48474141
PT
411 /* Is not an elemental subroutine call with array valued arguments. */
412 if (ss == gfc_ss_terminator)
6de9cd9a 413 {
48474141 414
5c5ce609
HA
415 if (is_intrinsic_mvbits)
416 {
417 has_alternate_specifier = 0;
418 gfc_conv_intrinsic_mvbits (&se, code->ext.actual, NULL);
419 }
420 else
421 {
422 /* Translate the call. */
423 has_alternate_specifier =
424 gfc_conv_procedure_call (&se, code->resolved_sym,
425 code->ext.actual, code->expr1, NULL);
48474141 426
5c5ce609
HA
427 /* A subroutine without side-effect, by definition, does nothing! */
428 TREE_SIDE_EFFECTS (se.expr) = 1;
429 }
48474141
PT
430
431 /* Chain the pieces together and return the block. */
432 if (has_alternate_specifier)
433 {
434 gfc_code *select_code;
435 gfc_symbol *sym;
436 select_code = code->next;
437 gcc_assert(select_code->op == EXEC_SELECT);
a513927a 438 sym = select_code->expr1->symtree->n.sym;
48474141 439 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
9ebe2d22
PT
440 if (sym->backend_decl == NULL)
441 sym->backend_decl = gfc_get_symbol_decl (sym);
726a989a 442 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
48474141
PT
443 }
444 else
445 gfc_add_expr_to_block (&se.pre, se.expr);
446
447 gfc_add_block_to_block (&se.pre, &se.post);
6de9cd9a 448 }
48474141 449
6de9cd9a 450 else
48474141
PT
451 {
452 /* An elemental subroutine call with array valued arguments has
453 to be scalarized. */
454 gfc_loopinfo loop;
455 stmtblock_t body;
456 stmtblock_t block;
457 gfc_se loopse;
70e72065 458 gfc_se depse;
48474141
PT
459
460 /* gfc_walk_elemental_function_args renders the ss chain in the
12f681a0 461 reverse order to the actual argument order. */
48474141
PT
462 ss = gfc_reverse_ss (ss);
463
464 /* Initialize the loop. */
465 gfc_init_se (&loopse, NULL);
466 gfc_init_loopinfo (&loop);
467 gfc_add_ss_to_loop (&loop, ss);
468
469 gfc_conv_ss_startstride (&loop);
8b704316
PT
470 /* TODO: gfc_conv_loop_setup generates a temporary for vector
471 subscripts. This could be prevented in the elemental case
472 as temporaries are handled separatedly
2b0bd714 473 (below in gfc_conv_elemental_dependencies). */
88016532
JD
474 if (code->expr1)
475 gfc_conv_loop_setup (&loop, &code->expr1->where);
476 else
477 gfc_conv_loop_setup (&loop, &code->loc);
478
48474141
PT
479 gfc_mark_ss_chain_used (ss, 1);
480
476220e7
PT
481 /* Convert the arguments, checking for dependencies. */
482 gfc_copy_loopinfo_to_se (&loopse, &loop);
483 loopse.ss = ss;
484
06bcd751 485 /* For operator assignment, do dependency checking. */
476220e7 486 if (dependency_check)
2b0bd714
MM
487 check_variable = ELEM_CHECK_VARIABLE;
488 else
489 check_variable = ELEM_DONT_CHECK_VARIABLE;
70e72065
MM
490
491 gfc_init_se (&depse, NULL);
492 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
2b0bd714 493 code->ext.actual, check_variable);
476220e7 494
70e72065
MM
495 gfc_add_block_to_block (&loop.pre, &depse.pre);
496 gfc_add_block_to_block (&loop.post, &depse.post);
497
48474141
PT
498 /* Generate the loop body. */
499 gfc_start_scalarized_body (&loop, &body);
500 gfc_init_block (&block);
48474141 501
eb74e79b
PT
502 if (mask && count1)
503 {
504 /* Form the mask expression according to the mask. */
505 index = count1;
506 maskexpr = gfc_build_array_ref (mask, index, NULL);
507 if (invert)
bc98ed60
TB
508 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
509 TREE_TYPE (maskexpr), maskexpr);
eb74e79b
PT
510 }
511
5c5ce609
HA
512 if (is_intrinsic_mvbits)
513 {
514 has_alternate_specifier = 0;
515 gfc_conv_intrinsic_mvbits (&loopse, code->ext.actual, &loop);
516 }
517 else
518 {
519 /* Add the subroutine call to the block. */
520 gfc_conv_procedure_call (&loopse, code->resolved_sym,
521 code->ext.actual, code->expr1,
522 NULL);
523 }
eb74e79b
PT
524
525 if (mask && count1)
526 {
527 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
c2255bc4 528 build_empty_stmt (input_location));
eb74e79b 529 gfc_add_expr_to_block (&loopse.pre, tmp);
bc98ed60
TB
530 tmp = fold_build2_loc (input_location, PLUS_EXPR,
531 gfc_array_index_type,
532 count1, gfc_index_one_node);
eb74e79b
PT
533 gfc_add_modify (&loopse.pre, count1, tmp);
534 }
535 else
536 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
48474141
PT
537
538 gfc_add_block_to_block (&block, &loopse.pre);
539 gfc_add_block_to_block (&block, &loopse.post);
540
541 /* Finish up the loop block and the loop. */
542 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
543 gfc_trans_scalarizing_loops (&loop, &body);
544 gfc_add_block_to_block (&se.pre, &loop.pre);
545 gfc_add_block_to_block (&se.pre, &loop.post);
476220e7 546 gfc_add_block_to_block (&se.pre, &se.post);
48474141
PT
547 gfc_cleanup_loop (&loop);
548 }
6de9cd9a 549
6de9cd9a
DN
550 return gfc_finish_block (&se.pre);
551}
552
553
554/* Translate the RETURN statement. */
555
556tree
d74d8807 557gfc_trans_return (gfc_code * code)
6de9cd9a 558{
a513927a 559 if (code->expr1)
6de9cd9a
DN
560 {
561 gfc_se se;
562 tree tmp;
563 tree result;
564
da4c6ed8 565 /* If code->expr is not NULL, this return statement must appear
d74d8807 566 in a subroutine and current_fake_result_decl has already
6de9cd9a
DN
567 been generated. */
568
5f20c93a 569 result = gfc_get_fake_result_decl (NULL, 0);
6de9cd9a 570 if (!result)
d74d8807 571 {
db30e21c
JM
572 gfc_warning (0,
573 "An alternate return at %L without a * dummy argument",
48749dbc 574 &code->expr1->where);
d74d8807
DK
575 return gfc_generate_return ();
576 }
6de9cd9a
DN
577
578 /* Start a new block for this statement. */
579 gfc_init_se (&se, NULL);
580 gfc_start_block (&se.pre);
581
a513927a 582 gfc_conv_expr (&se, code->expr1);
6de9cd9a 583
ba3ff5c2
DK
584 /* Note that the actually returned expression is a simple value and
585 does not depend on any pointers or such; thus we can clean-up with
586 se.post before returning. */
bc98ed60
TB
587 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
588 result, fold_convert (TREE_TYPE (result),
589 se.expr));
6de9cd9a 590 gfc_add_expr_to_block (&se.pre, tmp);
ba3ff5c2 591 gfc_add_block_to_block (&se.pre, &se.post);
6de9cd9a 592
d74d8807 593 tmp = gfc_generate_return ();
6de9cd9a 594 gfc_add_expr_to_block (&se.pre, tmp);
6de9cd9a
DN
595 return gfc_finish_block (&se.pre);
596 }
d74d8807
DK
597
598 return gfc_generate_return ();
6de9cd9a
DN
599}
600
601
602/* Translate the PAUSE statement. We have to translate this statement
603 to a runtime library call. */
604
605tree
606gfc_trans_pause (gfc_code * code)
607{
6cc22cf4 608 tree gfc_int8_type_node = gfc_get_int_type (8);
6de9cd9a 609 gfc_se se;
6de9cd9a 610 tree tmp;
6de9cd9a
DN
611
612 /* Start a new block for this statement. */
613 gfc_init_se (&se, NULL);
614 gfc_start_block (&se.pre);
615
616
a513927a 617 if (code->expr1 == NULL)
6de9cd9a 618 {
6cc22cf4 619 tmp = build_int_cst (size_type_node, 0);
db3927fb 620 tmp = build_call_expr_loc (input_location,
6d1b0f92
JD
621 gfor_fndecl_pause_string, 2,
622 build_int_cst (pchar_type_node, 0), tmp);
623 }
624 else if (code->expr1->ts.type == BT_INTEGER)
625 {
626 gfc_conv_expr (&se, code->expr1);
627 tmp = build_call_expr_loc (input_location,
628 gfor_fndecl_pause_numeric, 1,
6cc22cf4 629 fold_convert (gfc_int8_type_node, se.expr));
6de9cd9a
DN
630 }
631 else
632 {
a513927a 633 gfc_conv_expr_reference (&se, code->expr1);
db3927fb
AH
634 tmp = build_call_expr_loc (input_location,
635 gfor_fndecl_pause_string, 2,
6cc22cf4
JB
636 se.expr, fold_convert (size_type_node,
637 se.string_length));
6de9cd9a
DN
638 }
639
6de9cd9a
DN
640 gfc_add_expr_to_block (&se.pre, tmp);
641
642 gfc_add_block_to_block (&se.pre, &se.post);
643
644 return gfc_finish_block (&se.pre);
645}
646
647
648/* Translate the STOP statement. We have to translate this statement
649 to a runtime library call. */
650
651tree
d0a4a61c 652gfc_trans_stop (gfc_code *code, bool error_stop)
6de9cd9a
DN
653{
654 gfc_se se;
6de9cd9a 655 tree tmp;
916b809f 656 tree quiet;
6de9cd9a
DN
657
658 /* Start a new block for this statement. */
659 gfc_init_se (&se, NULL);
660 gfc_start_block (&se.pre);
661
916b809f
HA
662 if (code->expr2)
663 {
664 gfc_conv_expr_val (&se, code->expr2);
665 quiet = fold_convert (boolean_type_node, se.expr);
666 }
667 else
668 quiet = boolean_false_node;
669
a513927a 670 if (code->expr1 == NULL)
6de9cd9a 671 {
3f5fabc0 672 tmp = build_int_cst (size_type_node, 0);
6d1b0f92 673 tmp = build_call_expr_loc (input_location,
60386f50 674 error_stop
f19626cf 675 ? (flag_coarray == GFC_FCOARRAY_LIB
60386f50
TB
676 ? gfor_fndecl_caf_error_stop_str
677 : gfor_fndecl_error_stop_string)
0daa7ed9
AF
678 : (flag_coarray == GFC_FCOARRAY_LIB
679 ? gfor_fndecl_caf_stop_str
680 : gfor_fndecl_stop_string),
dffb1e22 681 3, build_int_cst (pchar_type_node, 0), tmp,
916b809f 682 quiet);
6d1b0f92
JD
683 }
684 else if (code->expr1->ts.type == BT_INTEGER)
685 {
686 gfc_conv_expr (&se, code->expr1);
db3927fb 687 tmp = build_call_expr_loc (input_location,
60386f50 688 error_stop
f19626cf 689 ? (flag_coarray == GFC_FCOARRAY_LIB
60386f50
TB
690 ? gfor_fndecl_caf_error_stop
691 : gfor_fndecl_error_stop_numeric)
0daa7ed9
AF
692 : (flag_coarray == GFC_FCOARRAY_LIB
693 ? gfor_fndecl_caf_stop_numeric
dffb1e22
JB
694 : gfor_fndecl_stop_numeric), 2,
695 fold_convert (integer_type_node, se.expr),
916b809f 696 quiet);
6de9cd9a
DN
697 }
698 else
699 {
a513927a 700 gfc_conv_expr_reference (&se, code->expr1);
db3927fb 701 tmp = build_call_expr_loc (input_location,
60386f50 702 error_stop
f19626cf 703 ? (flag_coarray == GFC_FCOARRAY_LIB
60386f50
TB
704 ? gfor_fndecl_caf_error_stop_str
705 : gfor_fndecl_error_stop_string)
0daa7ed9
AF
706 : (flag_coarray == GFC_FCOARRAY_LIB
707 ? gfor_fndecl_caf_stop_str
708 : gfor_fndecl_stop_string),
dffb1e22
JB
709 3, se.expr, fold_convert (size_type_node,
710 se.string_length),
916b809f 711 quiet);
6de9cd9a
DN
712 }
713
6de9cd9a
DN
714 gfc_add_expr_to_block (&se.pre, tmp);
715
716 gfc_add_block_to_block (&se.pre, &se.post);
717
718 return gfc_finish_block (&se.pre);
719}
720
ef78bc3c
AV
721/* Translate the FAIL IMAGE statement. */
722
723tree
724gfc_trans_fail_image (gfc_code *code ATTRIBUTE_UNUSED)
725{
726 if (flag_coarray == GFC_FCOARRAY_LIB)
727 return build_call_expr_loc (input_location,
3489d80f 728 gfor_fndecl_caf_fail_image, 0);
ef78bc3c
AV
729 else
730 {
731 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
732 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
733 tree tmp = gfc_get_symbol_decl (exsym);
734 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
735 }
736}
737
f8862a1b
DR
738/* Translate the FORM TEAM statement. */
739
740tree
741gfc_trans_form_team (gfc_code *code)
742{
743 if (flag_coarray == GFC_FCOARRAY_LIB)
744 {
91ab2a1d
TB
745 gfc_se se;
746 gfc_se argse1, argse2;
747 tree team_id, team_type, tmp;
f8862a1b 748
91ab2a1d
TB
749 gfc_init_se (&se, NULL);
750 gfc_init_se (&argse1, NULL);
751 gfc_init_se (&argse2, NULL);
752 gfc_start_block (&se.pre);
753
754 gfc_conv_expr_val (&argse1, code->expr1);
755 gfc_conv_expr_val (&argse2, code->expr2);
756 team_id = fold_convert (integer_type_node, argse1.expr);
757 team_type = gfc_build_addr_expr (ppvoid_type_node, argse2.expr);
758
759 gfc_add_block_to_block (&se.pre, &argse1.pre);
760 gfc_add_block_to_block (&se.pre, &argse2.pre);
761 tmp = build_call_expr_loc (input_location,
762 gfor_fndecl_caf_form_team, 3,
763 team_id, team_type,
764 build_int_cst (integer_type_node, 0));
765 gfc_add_expr_to_block (&se.pre, tmp);
766 gfc_add_block_to_block (&se.pre, &argse1.post);
767 gfc_add_block_to_block (&se.pre, &argse2.post);
768 return gfc_finish_block (&se.pre);
f8862a1b
DR
769 }
770 else
771 {
772 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
773 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
774 tree tmp = gfc_get_symbol_decl (exsym);
775 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
776 }
777}
778
779/* Translate the CHANGE TEAM statement. */
780
781tree
782gfc_trans_change_team (gfc_code *code)
783{
784 if (flag_coarray == GFC_FCOARRAY_LIB)
785 {
786 gfc_se argse;
91ab2a1d 787 tree team_type, tmp;
f8862a1b
DR
788
789 gfc_init_se (&argse, NULL);
790 gfc_conv_expr_val (&argse, code->expr1);
791 team_type = gfc_build_addr_expr (ppvoid_type_node, argse.expr);
792
91ab2a1d
TB
793 tmp = build_call_expr_loc (input_location,
794 gfor_fndecl_caf_change_team, 2, team_type,
795 build_int_cst (integer_type_node, 0));
796 gfc_add_expr_to_block (&argse.pre, tmp);
797 gfc_add_block_to_block (&argse.pre, &argse.post);
798 return gfc_finish_block (&argse.pre);
f8862a1b
DR
799 }
800 else
801 {
802 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
803 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
804 tree tmp = gfc_get_symbol_decl (exsym);
805 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
806 }
807}
808
809/* Translate the END TEAM statement. */
810
811tree
812gfc_trans_end_team (gfc_code *code ATTRIBUTE_UNUSED)
813{
814 if (flag_coarray == GFC_FCOARRAY_LIB)
815 {
816 return build_call_expr_loc (input_location,
817 gfor_fndecl_caf_end_team, 1,
818 build_int_cst (pchar_type_node, 0));
819 }
820 else
821 {
822 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
823 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
824 tree tmp = gfc_get_symbol_decl (exsym);
825 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
826 }
827}
828
829/* Translate the SYNC TEAM statement. */
830
831tree
832gfc_trans_sync_team (gfc_code *code)
833{
834 if (flag_coarray == GFC_FCOARRAY_LIB)
835 {
836 gfc_se argse;
91ab2a1d 837 tree team_type, tmp;
f8862a1b
DR
838
839 gfc_init_se (&argse, NULL);
840 gfc_conv_expr_val (&argse, code->expr1);
841 team_type = gfc_build_addr_expr (ppvoid_type_node, argse.expr);
842
91ab2a1d
TB
843 tmp = build_call_expr_loc (input_location,
844 gfor_fndecl_caf_sync_team, 2,
845 team_type,
846 build_int_cst (integer_type_node, 0));
847 gfc_add_expr_to_block (&argse.pre, tmp);
848 gfc_add_block_to_block (&argse.pre, &argse.post);
849 return gfc_finish_block (&argse.pre);
f8862a1b
DR
850 }
851 else
852 {
853 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
854 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
855 tree tmp = gfc_get_symbol_decl (exsym);
856 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
857 }
858}
6de9cd9a 859
fea54935 860tree
9f3880d1 861gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
fea54935
TB
862{
863 gfc_se se, argse;
9f3880d1
TB
864 tree stat = NULL_TREE, stat2 = NULL_TREE;
865 tree lock_acquired = NULL_TREE, lock_acquired2 = NULL_TREE;
fea54935
TB
866
867 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
868 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
f19626cf 869 if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB)
8b704316 870 return NULL_TREE;
fea54935 871
fea54935
TB
872 if (code->expr2)
873 {
874 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
875 gfc_init_se (&argse, NULL);
876 gfc_conv_expr_val (&argse, code->expr2);
877 stat = argse.expr;
878 }
9f3880d1
TB
879 else if (flag_coarray == GFC_FCOARRAY_LIB)
880 stat = null_pointer_node;
fea54935
TB
881
882 if (code->expr4)
883 {
884 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
885 gfc_init_se (&argse, NULL);
886 gfc_conv_expr_val (&argse, code->expr4);
887 lock_acquired = argse.expr;
888 }
9f3880d1
TB
889 else if (flag_coarray == GFC_FCOARRAY_LIB)
890 lock_acquired = null_pointer_node;
891
892 gfc_start_block (&se.pre);
893 if (flag_coarray == GFC_FCOARRAY_LIB)
894 {
895 tree tmp, token, image_index, errmsg, errmsg_len;
0f97b81b 896 tree index = build_zero_cst (gfc_array_index_type);
9f3880d1
TB
897 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
898
899 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
900 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
901 != INTMOD_ISO_FORTRAN_ENV
902 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
903 != ISOFORTRAN_LOCK_TYPE)
904 {
905 gfc_error ("Sorry, the lock component of derived type at %L is not "
906 "yet supported", &code->expr1->where);
907 return NULL_TREE;
908 }
909
3c9f5092
AV
910 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
911 code->expr1);
9f3880d1
TB
912
913 if (gfc_is_coindexed (code->expr1))
914 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
915 else
916 image_index = integer_zero_node;
917
918 /* For arrays, obtain the array index. */
919 if (gfc_expr_attr (code->expr1).dimension)
920 {
921 tree desc, tmp, extent, lbound, ubound;
922 gfc_array_ref *ar, ar2;
923 int i;
924
925 /* TODO: Extend this, once DT components are supported. */
926 ar = &code->expr1->ref->u.ar;
927 ar2 = *ar;
928 memset (ar, '\0', sizeof (*ar));
929 ar->as = ar2.as;
930 ar->type = AR_FULL;
931
932 gfc_init_se (&argse, NULL);
933 argse.descriptor_only = 1;
934 gfc_conv_expr_descriptor (&argse, code->expr1);
935 gfc_add_block_to_block (&se.pre, &argse.pre);
936 desc = argse.expr;
937 *ar = ar2;
938
0f97b81b 939 extent = build_one_cst (gfc_array_index_type);
9f3880d1
TB
940 for (i = 0; i < ar->dimen; i++)
941 {
942 gfc_init_se (&argse, NULL);
0f97b81b 943 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
9f3880d1
TB
944 gfc_add_block_to_block (&argse.pre, &argse.pre);
945 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
946 tmp = fold_build2_loc (input_location, MINUS_EXPR,
0f97b81b 947 TREE_TYPE (lbound), argse.expr, lbound);
9f3880d1 948 tmp = fold_build2_loc (input_location, MULT_EXPR,
0f97b81b 949 TREE_TYPE (tmp), extent, tmp);
9f3880d1 950 index = fold_build2_loc (input_location, PLUS_EXPR,
0f97b81b 951 TREE_TYPE (tmp), index, tmp);
9f3880d1
TB
952 if (i < ar->dimen - 1)
953 {
954 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
955 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
9f3880d1 956 extent = fold_build2_loc (input_location, MULT_EXPR,
0f97b81b 957 TREE_TYPE (tmp), extent, tmp);
9f3880d1
TB
958 }
959 }
960 }
961
962 /* errmsg. */
963 if (code->expr3)
964 {
965 gfc_init_se (&argse, NULL);
5df445a2 966 argse.want_pointer = 1;
9f3880d1
TB
967 gfc_conv_expr (&argse, code->expr3);
968 gfc_add_block_to_block (&se.pre, &argse.pre);
969 errmsg = argse.expr;
3f5fabc0 970 errmsg_len = fold_convert (size_type_node, argse.string_length);
9f3880d1
TB
971 }
972 else
973 {
974 errmsg = null_pointer_node;
3f5fabc0 975 errmsg_len = build_zero_cst (size_type_node);
9f3880d1
TB
976 }
977
978 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
979 {
980 stat2 = stat;
981 stat = gfc_create_var (integer_type_node, "stat");
982 }
983
984 if (lock_acquired != null_pointer_node
985 && TREE_TYPE (lock_acquired) != integer_type_node)
986 {
987 lock_acquired2 = lock_acquired;
988 lock_acquired = gfc_create_var (integer_type_node, "acquired");
989 }
990
0f97b81b 991 index = fold_convert (size_type_node, index);
9f3880d1
TB
992 if (op == EXEC_LOCK)
993 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
994 token, index, image_index,
995 lock_acquired != null_pointer_node
996 ? gfc_build_addr_expr (NULL, lock_acquired)
997 : lock_acquired,
998 stat != null_pointer_node
999 ? gfc_build_addr_expr (NULL, stat) : stat,
1000 errmsg, errmsg_len);
1001 else
1002 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1003 token, index, image_index,
1004 stat != null_pointer_node
1005 ? gfc_build_addr_expr (NULL, stat) : stat,
1006 errmsg, errmsg_len);
1007 gfc_add_expr_to_block (&se.pre, tmp);
1008
985f6c79
TB
1009 /* It guarantees memory consistency within the same segment */
1010 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1011 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1012 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1013 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1014 ASM_VOLATILE_P (tmp) = 1;
1015
1016 gfc_add_expr_to_block (&se.pre, tmp);
1017
9f3880d1
TB
1018 if (stat2 != NULL_TREE)
1019 gfc_add_modify (&se.pre, stat2,
1020 fold_convert (TREE_TYPE (stat2), stat));
1021
1022 if (lock_acquired2 != NULL_TREE)
1023 gfc_add_modify (&se.pre, lock_acquired2,
1024 fold_convert (TREE_TYPE (lock_acquired2),
1025 lock_acquired));
1026
1027 return gfc_finish_block (&se.pre);
1028 }
fea54935
TB
1029
1030 if (stat != NULL_TREE)
1031 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1032
1033 if (lock_acquired != NULL_TREE)
1034 gfc_add_modify (&se.pre, lock_acquired,
1035 fold_convert (TREE_TYPE (lock_acquired),
1036 boolean_true_node));
1037
1038 return gfc_finish_block (&se.pre);
1039}
1040
5df445a2
TB
1041tree
1042gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
1043{
1044 gfc_se se, argse;
1045 tree stat = NULL_TREE, stat2 = NULL_TREE;
1046 tree until_count = NULL_TREE;
1047
1048 if (code->expr2)
1049 {
1050 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
1051 gfc_init_se (&argse, NULL);
1052 gfc_conv_expr_val (&argse, code->expr2);
1053 stat = argse.expr;
1054 }
1055 else if (flag_coarray == GFC_FCOARRAY_LIB)
1056 stat = null_pointer_node;
1057
1058 if (code->expr4)
1059 {
1060 gfc_init_se (&argse, NULL);
1061 gfc_conv_expr_val (&argse, code->expr4);
1062 until_count = fold_convert (integer_type_node, argse.expr);
1063 }
1064 else
1065 until_count = integer_one_node;
1066
1067 if (flag_coarray != GFC_FCOARRAY_LIB)
1068 {
1069 gfc_start_block (&se.pre);
1070 gfc_init_se (&argse, NULL);
1071 gfc_conv_expr_val (&argse, code->expr1);
1072
1073 if (op == EXEC_EVENT_POST)
1074 gfc_add_modify (&se.pre, argse.expr,
1075 fold_build2_loc (input_location, PLUS_EXPR,
1076 TREE_TYPE (argse.expr), argse.expr,
1077 build_int_cst (TREE_TYPE (argse.expr), 1)));
1078 else
1079 gfc_add_modify (&se.pre, argse.expr,
1080 fold_build2_loc (input_location, MINUS_EXPR,
1081 TREE_TYPE (argse.expr), argse.expr,
1082 fold_convert (TREE_TYPE (argse.expr),
1083 until_count)));
1084 if (stat != NULL_TREE)
1085 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1086
1087 return gfc_finish_block (&se.pre);
1088 }
1089
1090 gfc_start_block (&se.pre);
1091 tree tmp, token, image_index, errmsg, errmsg_len;
0f97b81b 1092 tree index = build_zero_cst (gfc_array_index_type);
5df445a2
TB
1093 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
1094
1095 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
1096 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
1097 != INTMOD_ISO_FORTRAN_ENV
1098 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
1099 != ISOFORTRAN_EVENT_TYPE)
1100 {
1101 gfc_error ("Sorry, the event component of derived type at %L is not "
1102 "yet supported", &code->expr1->where);
1103 return NULL_TREE;
1104 }
1105
3c9f5092
AV
1106 gfc_init_se (&argse, NULL);
1107 gfc_get_caf_token_offset (&argse, &token, NULL, caf_decl, NULL_TREE,
1108 code->expr1);
1109 gfc_add_block_to_block (&se.pre, &argse.pre);
5df445a2
TB
1110
1111 if (gfc_is_coindexed (code->expr1))
1112 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
1113 else
1114 image_index = integer_zero_node;
1115
1116 /* For arrays, obtain the array index. */
1117 if (gfc_expr_attr (code->expr1).dimension)
1118 {
1119 tree desc, tmp, extent, lbound, ubound;
1120 gfc_array_ref *ar, ar2;
1121 int i;
1122
1123 /* TODO: Extend this, once DT components are supported. */
1124 ar = &code->expr1->ref->u.ar;
1125 ar2 = *ar;
1126 memset (ar, '\0', sizeof (*ar));
1127 ar->as = ar2.as;
1128 ar->type = AR_FULL;
1129
1130 gfc_init_se (&argse, NULL);
1131 argse.descriptor_only = 1;
1132 gfc_conv_expr_descriptor (&argse, code->expr1);
1133 gfc_add_block_to_block (&se.pre, &argse.pre);
1134 desc = argse.expr;
1135 *ar = ar2;
1136
0f97b81b 1137 extent = build_one_cst (gfc_array_index_type);
5df445a2
TB
1138 for (i = 0; i < ar->dimen; i++)
1139 {
1140 gfc_init_se (&argse, NULL);
0f97b81b 1141 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
5df445a2
TB
1142 gfc_add_block_to_block (&argse.pre, &argse.pre);
1143 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1144 tmp = fold_build2_loc (input_location, MINUS_EXPR,
0f97b81b 1145 TREE_TYPE (lbound), argse.expr, lbound);
5df445a2 1146 tmp = fold_build2_loc (input_location, MULT_EXPR,
0f97b81b 1147 TREE_TYPE (tmp), extent, tmp);
5df445a2 1148 index = fold_build2_loc (input_location, PLUS_EXPR,
0f97b81b 1149 TREE_TYPE (tmp), index, tmp);
5df445a2
TB
1150 if (i < ar->dimen - 1)
1151 {
1152 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1153 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
5df445a2 1154 extent = fold_build2_loc (input_location, MULT_EXPR,
0f97b81b 1155 TREE_TYPE (tmp), extent, tmp);
5df445a2
TB
1156 }
1157 }
1158 }
1159
1160 /* errmsg. */
1161 if (code->expr3)
1162 {
1163 gfc_init_se (&argse, NULL);
1164 argse.want_pointer = 1;
1165 gfc_conv_expr (&argse, code->expr3);
1166 gfc_add_block_to_block (&se.pre, &argse.pre);
1167 errmsg = argse.expr;
3f5fabc0 1168 errmsg_len = fold_convert (size_type_node, argse.string_length);
5df445a2
TB
1169 }
1170 else
1171 {
1172 errmsg = null_pointer_node;
3f5fabc0 1173 errmsg_len = build_zero_cst (size_type_node);
5df445a2
TB
1174 }
1175
1176 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
1177 {
1178 stat2 = stat;
1179 stat = gfc_create_var (integer_type_node, "stat");
1180 }
1181
cbd29d0e 1182 index = fold_convert (size_type_node, index);
5df445a2
TB
1183 if (op == EXEC_EVENT_POST)
1184 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6,
1185 token, index, image_index,
1186 stat != null_pointer_node
1187 ? gfc_build_addr_expr (NULL, stat) : stat,
1188 errmsg, errmsg_len);
1189 else
1190 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6,
1191 token, index, until_count,
1192 stat != null_pointer_node
1193 ? gfc_build_addr_expr (NULL, stat) : stat,
1194 errmsg, errmsg_len);
1195 gfc_add_expr_to_block (&se.pre, tmp);
1196
985f6c79
TB
1197 /* It guarantees memory consistency within the same segment */
1198 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1199 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1200 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1201 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1202 ASM_VOLATILE_P (tmp) = 1;
1203 gfc_add_expr_to_block (&se.pre, tmp);
1204
5df445a2
TB
1205 if (stat2 != NULL_TREE)
1206 gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat));
1207
1208 return gfc_finish_block (&se.pre);
1209}
fea54935 1210
d0a4a61c 1211tree
60386f50 1212gfc_trans_sync (gfc_code *code, gfc_exec_op type)
d0a4a61c 1213{
60386f50
TB
1214 gfc_se se, argse;
1215 tree tmp;
1216 tree images = NULL_TREE, stat = NULL_TREE,
1217 errmsg = NULL_TREE, errmsglen = NULL_TREE;
d0a4a61c 1218
60386f50
TB
1219 /* Short cut: For single images without bound checking or without STAT=,
1220 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
1221 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
f19626cf 1222 && flag_coarray != GFC_FCOARRAY_LIB)
8b704316 1223 return NULL_TREE;
60386f50
TB
1224
1225 gfc_init_se (&se, NULL);
1226 gfc_start_block (&se.pre);
1227
1228 if (code->expr1 && code->expr1->rank == 0)
d0a4a61c 1229 {
60386f50
TB
1230 gfc_init_se (&argse, NULL);
1231 gfc_conv_expr_val (&argse, code->expr1);
1232 images = argse.expr;
1233 }
1234
1235 if (code->expr2)
1236 {
bbf19f9c
HA
1237 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE
1238 || code->expr2->expr_type == EXPR_FUNCTION);
60386f50
TB
1239 gfc_init_se (&argse, NULL);
1240 gfc_conv_expr_val (&argse, code->expr2);
1241 stat = argse.expr;
1242 }
f5c01f5b
DC
1243 else
1244 stat = null_pointer_node;
60386f50 1245
9315dff0 1246 if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB)
60386f50 1247 {
bbf19f9c
HA
1248 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE
1249 || code->expr3->expr_type == EXPR_FUNCTION);
60386f50 1250 gfc_init_se (&argse, NULL);
5df445a2 1251 argse.want_pointer = 1;
60386f50
TB
1252 gfc_conv_expr (&argse, code->expr3);
1253 gfc_conv_string_parameter (&argse);
f5c01f5b 1254 errmsg = gfc_build_addr_expr (NULL, argse.expr);
3f5fabc0 1255 errmsglen = fold_convert (size_type_node, argse.string_length);
60386f50 1256 }
9315dff0 1257 else if (flag_coarray == GFC_FCOARRAY_LIB)
60386f50
TB
1258 {
1259 errmsg = null_pointer_node;
3f5fabc0 1260 errmsglen = build_int_cst (size_type_node, 0);
d0a4a61c
TB
1261 }
1262
1263 /* Check SYNC IMAGES(imageset) for valid image index.
1cc0e193 1264 FIXME: Add a check for image-set arrays. */
d0a4a61c
TB
1265 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1266 && code->expr1->rank == 0)
1267 {
e6cc67f6 1268 tree images2 = fold_convert (integer_type_node, images);
d0a4a61c 1269 tree cond;
f19626cf 1270 if (flag_coarray != GFC_FCOARRAY_LIB)
63ee5404 1271 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
60386f50
TB
1272 images, build_int_cst (TREE_TYPE (images), 1));
1273 else
1274 {
1275 tree cond2;
a8a5f4a9
TB
1276 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
1277 2, integer_zero_node,
1278 build_int_cst (integer_type_node, -1));
63ee5404 1279 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
e6cc67f6 1280 images2, tmp);
63ee5404 1281 cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
60386f50
TB
1282 images,
1283 build_int_cst (TREE_TYPE (images), 1));
45d5889a 1284 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
63ee5404 1285 logical_type_node, cond, cond2);
60386f50 1286 }
d0a4a61c
TB
1287 gfc_trans_runtime_check (true, false, cond, &se.pre,
1288 &code->expr1->where, "Invalid image number "
e6cc67f6 1289 "%d in SYNC IMAGES", images2);
d0a4a61c
TB
1290 }
1291
985f6c79
TB
1292 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
1293 image control statements SYNC IMAGES and SYNC ALL. */
1294 if (flag_coarray == GFC_FCOARRAY_LIB)
1295 {
1296 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1297 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1298 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1299 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1300 ASM_VOLATILE_P (tmp) = 1;
1301 gfc_add_expr_to_block (&se.pre, tmp);
1302 }
1303
9315dff0 1304 if (flag_coarray != GFC_FCOARRAY_LIB)
d0a4a61c 1305 {
60386f50
TB
1306 /* Set STAT to zero. */
1307 if (code->expr2)
1308 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1309 }
9315dff0 1310 else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY)
60386f50 1311 {
f5c01f5b
DC
1312 /* SYNC ALL => stat == null_pointer_node
1313 SYNC ALL(stat=s) => stat has an integer type
1314
1315 If "stat" has the wrong integer type, use a temp variable of
1316 the right type and later cast the result back into "stat". */
1317 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1318 {
1319 if (TREE_TYPE (stat) == integer_type_node)
1320 stat = gfc_build_addr_expr (NULL, stat);
8b704316 1321
9315dff0
AF
1322 if(type == EXEC_SYNC_MEMORY)
1323 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory,
1324 3, stat, errmsg, errmsglen);
1325 else
1326 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1327 3, stat, errmsg, errmsglen);
1328
f5c01f5b
DC
1329 gfc_add_expr_to_block (&se.pre, tmp);
1330 }
60386f50 1331 else
f5c01f5b
DC
1332 {
1333 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1334
1335 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1336 3, gfc_build_addr_expr (NULL, tmp_stat),
1337 errmsg, errmsglen);
1338 gfc_add_expr_to_block (&se.pre, tmp);
8b704316 1339
f5c01f5b
DC
1340 gfc_add_modify (&se.pre, stat,
1341 fold_convert (TREE_TYPE (stat), tmp_stat));
1342 }
60386f50
TB
1343 }
1344 else
1345 {
1346 tree len;
1347
1348 gcc_assert (type == EXEC_SYNC_IMAGES);
1349
1350 if (!code->expr1)
1351 {
1352 len = build_int_cst (integer_type_node, -1);
1353 images = null_pointer_node;
1354 }
1355 else if (code->expr1->rank == 0)
1356 {
1357 len = build_int_cst (integer_type_node, 1);
1358 images = gfc_build_addr_expr (NULL_TREE, images);
1359 }
1360 else
1361 {
1362 /* FIXME. */
1363 if (code->expr1->ts.kind != gfc_c_int_kind)
29e0597e
TB
1364 gfc_fatal_error ("Sorry, only support for integer kind %d "
1365 "implemented for image-set at %L",
1366 gfc_c_int_kind, &code->expr1->where);
60386f50 1367
2960a368 1368 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
60386f50
TB
1369 images = se.expr;
1370
1371 tmp = gfc_typenode_for_spec (&code->expr1->ts);
1372 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
1373 tmp = gfc_get_element_type (tmp);
1374
1375 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1376 TREE_TYPE (len), len,
1377 fold_convert (TREE_TYPE (len),
1378 TYPE_SIZE_UNIT (tmp)));
1379 len = fold_convert (integer_type_node, len);
1380 }
1381
f5c01f5b
DC
1382 /* SYNC IMAGES(imgs) => stat == null_pointer_node
1383 SYNC IMAGES(imgs,stat=s) => stat has an integer type
1384
1385 If "stat" has the wrong integer type, use a temp variable of
1386 the right type and later cast the result back into "stat". */
1387 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1388 {
1389 if (TREE_TYPE (stat) == integer_type_node)
1390 stat = gfc_build_addr_expr (NULL, stat);
1391
8b704316 1392 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
f5c01f5b
DC
1393 5, fold_convert (integer_type_node, len),
1394 images, stat, errmsg, errmsglen);
1395 gfc_add_expr_to_block (&se.pre, tmp);
1396 }
60386f50 1397 else
f5c01f5b
DC
1398 {
1399 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1400
8b704316 1401 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
f5c01f5b
DC
1402 5, fold_convert (integer_type_node, len),
1403 images, gfc_build_addr_expr (NULL, tmp_stat),
1404 errmsg, errmsglen);
1405 gfc_add_expr_to_block (&se.pre, tmp);
1406
8b704316 1407 gfc_add_modify (&se.pre, stat,
f5c01f5b
DC
1408 fold_convert (TREE_TYPE (stat), tmp_stat));
1409 }
d0a4a61c
TB
1410 }
1411
60386f50 1412 return gfc_finish_block (&se.pre);
d0a4a61c
TB
1413}
1414
1415
6de9cd9a
DN
1416/* Generate GENERIC for the IF construct. This function also deals with
1417 the simple IF statement, because the front end translates the IF
1418 statement into an IF construct.
1419
1420 We translate:
1421
1422 IF (cond) THEN
1423 then_clause
1424 ELSEIF (cond2)
1425 elseif_clause
1426 ELSE
1427 else_clause
1428 ENDIF
1429
1430 into:
1431
1432 pre_cond_s;
1433 if (cond_s)
1434 {
1435 then_clause;
1436 }
1437 else
1438 {
1439 pre_cond_s
1440 if (cond_s)
1441 {
1442 elseif_clause
1443 }
1444 else
1445 {
1446 else_clause;
1447 }
1448 }
1449
1450 where COND_S is the simplified version of the predicate. PRE_COND_S
1451 are the pre side-effects produced by the translation of the
1452 conditional.
1453 We need to build the chain recursively otherwise we run into
1454 problems with folding incomplete statements. */
1455
1456static tree
1457gfc_trans_if_1 (gfc_code * code)
1458{
1459 gfc_se if_se;
1460 tree stmt, elsestmt;
e84589e1 1461 locus saved_loc;
55bd9c35 1462 location_t loc;
6de9cd9a
DN
1463
1464 /* Check for an unconditional ELSE clause. */
a513927a 1465 if (!code->expr1)
6de9cd9a
DN
1466 return gfc_trans_code (code->next);
1467
1468 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
1469 gfc_init_se (&if_se, NULL);
1470 gfc_start_block (&if_se.pre);
1471
1472 /* Calculate the IF condition expression. */
e84589e1
TB
1473 if (code->expr1->where.lb)
1474 {
1475 gfc_save_backend_locus (&saved_loc);
1476 gfc_set_backend_locus (&code->expr1->where);
1477 }
1478
a513927a 1479 gfc_conv_expr_val (&if_se, code->expr1);
6de9cd9a 1480
e84589e1
TB
1481 if (code->expr1->where.lb)
1482 gfc_restore_backend_locus (&saved_loc);
1483
6de9cd9a
DN
1484 /* Translate the THEN clause. */
1485 stmt = gfc_trans_code (code->next);
1486
1487 /* Translate the ELSE clause. */
1488 if (code->block)
1489 elsestmt = gfc_trans_if_1 (code->block);
1490 else
c2255bc4 1491 elsestmt = build_empty_stmt (input_location);
6de9cd9a
DN
1492
1493 /* Build the condition expression and add it to the condition block. */
9c81750c
TB
1494 loc = code->expr1->where.lb ? gfc_get_location (&code->expr1->where)
1495 : input_location;
55bd9c35
TB
1496 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
1497 elsestmt);
8b704316 1498
6de9cd9a
DN
1499 gfc_add_expr_to_block (&if_se.pre, stmt);
1500
1501 /* Finish off this statement. */
1502 return gfc_finish_block (&if_se.pre);
1503}
1504
1505tree
1506gfc_trans_if (gfc_code * code)
1507{
e5ca9693
DK
1508 stmtblock_t body;
1509 tree exit_label;
1510
1511 /* Create exit label so it is available for trans'ing the body code. */
1512 exit_label = gfc_build_label_decl (NULL_TREE);
1513 code->exit_label = exit_label;
1514
1515 /* Translate the actual code in code->block. */
1516 gfc_init_block (&body);
1517 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1518
1519 /* Add exit label. */
1520 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
6de9cd9a 1521
e5ca9693 1522 return gfc_finish_block (&body);
6de9cd9a
DN
1523}
1524
1525
fa951694 1526/* Translate an arithmetic IF expression.
6de9cd9a
DN
1527
1528 IF (cond) label1, label2, label3 translates to
1529
1530 if (cond <= 0)
1531 {
1532 if (cond < 0)
1533 goto label1;
1534 else // cond == 0
1535 goto label2;
1536 }
1537 else // cond > 0
1538 goto label3;
442c1644
CY
1539
1540 An optimized version can be generated in case of equal labels.
1541 E.g., if label1 is equal to label2, we can translate it to
1542
1543 if (cond <= 0)
1544 goto label1;
1545 else
1546 goto label3;
6de9cd9a
DN
1547*/
1548
1549tree
1550gfc_trans_arithmetic_if (gfc_code * code)
1551{
1552 gfc_se se;
1553 tree tmp;
1554 tree branch1;
1555 tree branch2;
1556 tree zero;
1557
1558 /* Start a new block. */
1559 gfc_init_se (&se, NULL);
1560 gfc_start_block (&se.pre);
1561
1562 /* Pre-evaluate COND. */
a513927a 1563 gfc_conv_expr_val (&se, code->expr1);
5ec1334b 1564 se.expr = gfc_evaluate_now (se.expr, &se.pre);
6de9cd9a
DN
1565
1566 /* Build something to compare with. */
1567 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1568
79bd1948 1569 if (code->label1->value != code->label2->value)
442c1644
CY
1570 {
1571 /* If (cond < 0) take branch1 else take branch2.
1572 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
79bd1948 1573 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
442c1644
CY
1574 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1575
79bd1948 1576 if (code->label1->value != code->label3->value)
63ee5404 1577 tmp = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
bc98ed60 1578 se.expr, zero);
442c1644 1579 else
63ee5404 1580 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
bc98ed60 1581 se.expr, zero);
6de9cd9a 1582
bc98ed60
TB
1583 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1584 tmp, branch1, branch2);
442c1644
CY
1585 }
1586 else
79bd1948 1587 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
6de9cd9a 1588
79bd1948 1589 if (code->label1->value != code->label3->value
442c1644
CY
1590 && code->label2->value != code->label3->value)
1591 {
1592 /* if (cond <= 0) take branch1 else take branch2. */
1593 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
63ee5404 1594 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
bc98ed60
TB
1595 se.expr, zero);
1596 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1597 tmp, branch1, branch2);
442c1644 1598 }
6de9cd9a
DN
1599
1600 /* Append the COND_EXPR to the evaluation of COND, and return. */
1601 gfc_add_expr_to_block (&se.pre, branch1);
1602 return gfc_finish_block (&se.pre);
1603}
1604
1605
1cc0e193 1606/* Translate a CRITICAL block. */
d0a4a61c
TB
1607tree
1608gfc_trans_critical (gfc_code *code)
1609{
1610 stmtblock_t block;
bc0229f9 1611 tree tmp, token = NULL_TREE;
d0a4a61c
TB
1612
1613 gfc_start_block (&block);
60386f50 1614
f19626cf 1615 if (flag_coarray == GFC_FCOARRAY_LIB)
60386f50 1616 {
0f09fc8a 1617 tree zero_size = build_zero_cst (size_type_node);
bc0229f9
TB
1618 token = gfc_get_symbol_decl (code->resolved_sym);
1619 token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
1620 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
0f09fc8a 1621 token, zero_size, integer_one_node,
9de8e7af 1622 null_pointer_node, null_pointer_node,
0f09fc8a 1623 null_pointer_node, zero_size);
60386f50 1624 gfc_add_expr_to_block (&block, tmp);
985f6c79
TB
1625
1626 /* It guarantees memory consistency within the same segment */
1627 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1628 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1629 gfc_build_string_const (1, ""),
1630 NULL_TREE, NULL_TREE,
1631 tree_cons (NULL_TREE, tmp, NULL_TREE),
1632 NULL_TREE);
1633 ASM_VOLATILE_P (tmp) = 1;
afbc5ae8 1634
985f6c79 1635 gfc_add_expr_to_block (&block, tmp);
60386f50
TB
1636 }
1637
d0a4a61c
TB
1638 tmp = gfc_trans_code (code->block->next);
1639 gfc_add_expr_to_block (&block, tmp);
1640
f19626cf 1641 if (flag_coarray == GFC_FCOARRAY_LIB)
60386f50 1642 {
0f09fc8a 1643 tree zero_size = build_zero_cst (size_type_node);
bc0229f9 1644 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
0f09fc8a 1645 token, zero_size, integer_one_node,
bc0229f9 1646 null_pointer_node, null_pointer_node,
0f09fc8a 1647 zero_size);
60386f50 1648 gfc_add_expr_to_block (&block, tmp);
60386f50 1649
985f6c79
TB
1650 /* It guarantees memory consistency within the same segment */
1651 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1652 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1653 gfc_build_string_const (1, ""),
1654 NULL_TREE, NULL_TREE,
1655 tree_cons (NULL_TREE, tmp, NULL_TREE),
1656 NULL_TREE);
1657 ASM_VOLATILE_P (tmp) = 1;
1658
1659 gfc_add_expr_to_block (&block, tmp);
1660 }
60386f50 1661
d0a4a61c
TB
1662 return gfc_finish_block (&block);
1663}
1664
1665
5b384b3d
PT
1666/* Return true, when the class has a _len component. */
1667
1668static bool
1669class_has_len_component (gfc_symbol *sym)
1670{
1671 gfc_component *comp = sym->ts.u.derived->components;
1672 while (comp)
1673 {
1674 if (strcmp (comp->name, "_len") == 0)
1675 return true;
1676 comp = comp->next;
1677 }
1678 return false;
1679}
1680
1681
70570ec1
PT
1682static void
1683copy_descriptor (stmtblock_t *block, tree dst, tree src, int rank)
1684{
1685 int n;
1686 tree dim;
1687 tree tmp;
1688 tree tmp2;
1689 tree size;
1690 tree offset;
1691
1692 offset = gfc_index_zero_node;
1693
1694 /* Use memcpy to copy the descriptor. The size is the minimum of
1695 the sizes of 'src' and 'dst'. This avoids a non-trivial conversion. */
1696 tmp = TYPE_SIZE_UNIT (TREE_TYPE (src));
1697 tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (dst));
1698 size = fold_build2_loc (input_location, MIN_EXPR,
1699 TREE_TYPE (tmp), tmp, tmp2);
1700 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
1701 tmp = build_call_expr_loc (input_location, tmp, 3,
1702 gfc_build_addr_expr (NULL_TREE, dst),
1703 gfc_build_addr_expr (NULL_TREE, src),
1704 fold_convert (size_type_node, size));
1705 gfc_add_expr_to_block (block, tmp);
1706
1707 /* Set the offset correctly. */
1708 for (n = 0; n < rank; n++)
1709 {
1710 dim = gfc_rank_cst[n];
1711 tmp = gfc_conv_descriptor_lbound_get (src, dim);
1712 tmp2 = gfc_conv_descriptor_stride_get (src, dim);
1713 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
1714 tmp, tmp2);
1715 offset = fold_build2_loc (input_location, MINUS_EXPR,
1716 TREE_TYPE (offset), offset, tmp);
1717 offset = gfc_evaluate_now (offset, block);
1718 }
1719
1720 gfc_conv_descriptor_offset_set (block, dst, offset);
1721}
1722
1723
6312ef45
JW
1724/* Do proper initialization for ASSOCIATE names. */
1725
1726static void
1727trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1728{
1729 gfc_expr *e;
1730 tree tmp;
c49ea23d 1731 bool class_target;
8b704316 1732 bool unlimited;
8f75db9f
PT
1733 tree desc;
1734 tree offset;
1735 tree dim;
1736 int n;
5b384b3d
PT
1737 tree charlen;
1738 bool need_len_assign;
ff3598bc
PT
1739 bool whole_array = true;
1740 gfc_ref *ref;
70570ec1 1741 gfc_symbol *sym2;
6312ef45
JW
1742
1743 gcc_assert (sym->assoc);
1744 e = sym->assoc->target;
1745
c49ea23d
PT
1746 class_target = (e->expr_type == EXPR_VARIABLE)
1747 && (gfc_is_class_scalar_expr (e)
1748 || gfc_is_class_array_ref (e, NULL));
1749
8b704316
PT
1750 unlimited = UNLIMITED_POLY (e);
1751
ff3598bc
PT
1752 for (ref = e->ref; ref; ref = ref->next)
1753 if (ref->type == REF_ARRAY
1754 && ref->u.ar.type == AR_FULL
1755 && ref->next)
1756 {
1757 whole_array = false;
1758 break;
1759 }
1760
5b384b3d
PT
1761 /* Assignments to the string length need to be generated, when
1762 ( sym is a char array or
1763 sym has a _len component)
1764 and the associated expression is unlimited polymorphic, which is
1765 not (yet) correctly in 'unlimited', because for an already associated
1766 BT_DERIVED the u-poly flag is not set, i.e.,
1767 __tmp_CHARACTER_0_1 => w => arg
1768 ^ generated temp ^ from code, the w does not have the u-poly
1769 flag set, where UNLIMITED_POLY(e) expects it. */
1770 need_len_assign = ((unlimited || (e->ts.type == BT_DERIVED
1771 && e->ts.u.derived->attr.unlimited_polymorphic))
1772 && (sym->ts.type == BT_CHARACTER
1773 || ((sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED)
70570ec1
PT
1774 && class_has_len_component (sym)))
1775 && !sym->attr.select_rank_temporary);
1776
6312ef45
JW
1777 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1778 to array temporary) for arrays with either unknown shape or if associating
70570ec1
PT
1779 to a variable. Select rank temporaries need somewhat different treatment
1780 to other associate names and case temporaries. This because the selector
1781 is assumed rank and so the offset in particular has to be changed. Also,
1782 the case temporaries carry both allocatable and target attributes if
1783 present in the selector. This means that an allocatation or change of
1784 association can occur and so has to be dealt with. */
1785 if (sym->attr.select_rank_temporary)
1786 {
1787 gfc_se se;
1788 tree class_decl = NULL_TREE;
1789 int rank = 0;
1790 bool class_ptr;
1791
1792 sym2 = e->symtree->n.sym;
1793 gfc_init_se (&se, NULL);
1794 if (e->ts.type == BT_CLASS)
1795 {
1796 /* Go straight to the class data. */
c4a67898 1797 if (sym2->attr.dummy && !sym2->attr.optional)
70570ec1 1798 {
8fa9e73e
SL
1799 class_decl = sym2->backend_decl;
1800 if (DECL_LANG_SPECIFIC (class_decl)
1801 && GFC_DECL_SAVED_DESCRIPTOR (class_decl))
1802 class_decl = GFC_DECL_SAVED_DESCRIPTOR (class_decl);
70570ec1
PT
1803 if (POINTER_TYPE_P (TREE_TYPE (class_decl)))
1804 class_decl = build_fold_indirect_ref_loc (input_location,
1805 class_decl);
1806 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (class_decl)));
1807 se.expr = gfc_class_data_get (class_decl);
1808 }
1809 else
1810 {
1811 class_decl = sym2->backend_decl;
1812 gfc_conv_expr_descriptor (&se, e);
1813 if (POINTER_TYPE_P (TREE_TYPE (se.expr)))
1814 se.expr = build_fold_indirect_ref_loc (input_location,
1815 se.expr);
1816 }
1817
1818 if (CLASS_DATA (sym)->as && CLASS_DATA (sym)->as->rank > 0)
1819 rank = CLASS_DATA (sym)->as->rank;
1820 }
1821 else
1822 {
1823 gfc_conv_expr_descriptor (&se, e);
1824 if (sym->as && sym->as->rank > 0)
1825 rank = sym->as->rank;
1826 }
1827
1828 desc = sym->backend_decl;
1829
1830 /* The SELECT TYPE mechanisms turn class temporaries into pointers, which
1831 point to the selector. */
1832 class_ptr = class_decl != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (desc));
1833 if (class_ptr)
1834 {
1835 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (desc)), "class");
1836 tmp = gfc_build_addr_expr (NULL, tmp);
1837 gfc_add_modify (&se.pre, desc, tmp);
1838
1839 tmp = gfc_class_vptr_get (class_decl);
1840 gfc_add_modify (&se.pre, gfc_class_vptr_get (desc), tmp);
1841 if (UNLIMITED_POLY (sym))
1842 gfc_add_modify (&se.pre, gfc_class_len_get (desc),
1843 gfc_class_len_get (class_decl));
1844
1845 desc = gfc_class_data_get (desc);
1846 }
1847
1848 /* SELECT RANK temporaries can carry the allocatable and pointer
1849 attributes so the selector descriptor must be copied in and
1850 copied out. */
1851 if (rank > 0)
1852 copy_descriptor (&se.pre, desc, se.expr, rank);
1853 else
1854 {
1855 tmp = gfc_conv_descriptor_data_get (se.expr);
1856 gfc_add_modify (&se.pre, desc,
1857 fold_convert (TREE_TYPE (desc), tmp));
1858 }
1859
1860 /* Deal with associate_name => selector. Class associate names are
1861 treated in the same way as in SELECT TYPE. */
1862 sym2 = sym->assoc->target->symtree->n.sym;
1863 if (sym2->assoc && sym->assoc->target && sym2->ts.type != BT_CLASS)
1864 {
1865 sym2 = sym2->assoc->target->symtree->n.sym;
1866 se.expr = sym2->backend_decl;
1867
1868 if (POINTER_TYPE_P (TREE_TYPE (se.expr)))
1869 se.expr = build_fold_indirect_ref_loc (input_location,
1870 se.expr);
1871 }
1872
1873 /* There could have been reallocation. Copy descriptor back to the
1874 selector and update the offset. */
1875 if (sym->attr.allocatable || sym->attr.pointer
1876 || (sym->ts.type == BT_CLASS
1877 && (CLASS_DATA (sym)->attr.allocatable
1878 || CLASS_DATA (sym)->attr.pointer)))
1879 {
1880 if (rank > 0)
1881 copy_descriptor (&se.post, se.expr, desc, rank);
1882 else
0313a84a 1883 gfc_conv_descriptor_data_set (&se.post, se.expr, desc);
70570ec1
PT
1884
1885 /* The dynamic type could have changed too. */
1886 if (sym->ts.type == BT_CLASS)
1887 {
1888 tmp = sym->backend_decl;
1889 if (class_ptr)
1890 tmp = build_fold_indirect_ref_loc (input_location, tmp);
1891 gfc_add_modify (&se.post, gfc_class_vptr_get (class_decl),
1892 gfc_class_vptr_get (tmp));
1893 if (UNLIMITED_POLY (sym))
1894 gfc_add_modify (&se.post, gfc_class_len_get (class_decl),
1895 gfc_class_len_get (tmp));
1896 }
1897 }
1898
1899 tmp = gfc_finish_block (&se.post);
1900
1901 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), tmp);
1902 }
1903 /* Now all the other kinds of associate variable. */
1904 else if (sym->attr.dimension && !class_target
1905 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
6312ef45
JW
1906 {
1907 gfc_se se;
6312ef45 1908 tree desc;
bcac046f 1909 bool cst_array_ctor;
6312ef45
JW
1910
1911 desc = sym->backend_decl;
bcac046f 1912 cst_array_ctor = e->expr_type == EXPR_ARRAY
84ee745e
PT
1913 && gfc_constant_array_constructor_p (e->value.constructor)
1914 && e->ts.type != BT_CHARACTER;
6312ef45
JW
1915
1916 /* If association is to an expression, evaluate it and create temporary.
1917 Otherwise, get descriptor of target for pointer assignment. */
1918 gfc_init_se (&se, NULL);
d5f48c7c 1919
bcac046f 1920 if (sym->assoc->variable || cst_array_ctor)
6312ef45
JW
1921 {
1922 se.direct_byref = 1;
1cf43a1d 1923 se.use_offset = 1;
6312ef45 1924 se.expr = desc;
d5f48c7c 1925 GFC_DECL_PTR_ARRAY_P (sym->backend_decl) = 1;
6312ef45 1926 }
1cf43a1d 1927
2960a368 1928 gfc_conv_expr_descriptor (&se, e);
6312ef45 1929
707905d0 1930 if (sym->ts.type == BT_CHARACTER
57da3493 1931 && sym->ts.deferred
707905d0
PT
1932 && !sym->attr.select_type_temporary
1933 && VAR_P (sym->ts.u.cl->backend_decl)
1934 && se.string_length != sym->ts.u.cl->backend_decl)
1935 {
1936 gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
f622221a 1937 fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
707905d0
PT
1938 se.string_length));
1939 }
1940
6312ef45
JW
1941 /* If we didn't already do the pointer assignment, set associate-name
1942 descriptor to the one generated for the temporary. */
ff3598bc
PT
1943 if ((!sym->assoc->variable && !cst_array_ctor)
1944 || !whole_array)
6312ef45
JW
1945 {
1946 int dim;
1947
ff3598bc
PT
1948 if (whole_array)
1949 gfc_add_modify (&se.pre, desc, se.expr);
6312ef45
JW
1950
1951 /* The generated descriptor has lower bound zero (as array
1952 temporary), shift bounds so we get lower bounds of 1. */
1953 for (dim = 0; dim < e->rank; ++dim)
1954 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1955 dim, gfc_index_one_node);
1956 }
1957
68b1c5e1
PT
1958 /* If this is a subreference array pointer associate name use the
1959 associate variable element size for the value of 'span'. */
d5f48c7c 1960 if (sym->attr.subref_array_pointer && !se.direct_byref)
68b1c5e1
PT
1961 {
1962 gcc_assert (e->expr_type == EXPR_VARIABLE);
f82f425b
PT
1963 tmp = gfc_get_array_span (se.expr, e);
1964
ff3598bc 1965 gfc_conv_descriptor_span_set (&se.pre, desc, tmp);
68b1c5e1
PT
1966 }
1967
0b627b58
PT
1968 if (e->expr_type == EXPR_FUNCTION
1969 && sym->ts.type == BT_DERIVED
1970 && sym->ts.u.derived
1971 && sym->ts.u.derived->attr.pdt_type)
1972 {
1973 tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, se.expr,
1974 sym->as->rank);
1975 gfc_add_expr_to_block (&se.post, tmp);
1976 }
1977
6312ef45
JW
1978 /* Done, register stuff as init / cleanup code. */
1979 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1980 gfc_finish_block (&se.post));
1981 }
1982
8b704316
PT
1983 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1984 arrays to be assigned directly. */
1985 else if (class_target && sym->attr.dimension
1986 && (sym->ts.type == BT_DERIVED || unlimited))
c49ea23d
PT
1987 {
1988 gfc_se se;
1989
1990 gfc_init_se (&se, NULL);
102344e2 1991 se.descriptor_only = 1;
f3b0bb7a
AV
1992 /* In a select type the (temporary) associate variable shall point to
1993 a standard fortran array (lower bound == 1), but conv_expr ()
1994 just maps to the input array in the class object, whose lbound may
1995 be arbitrary. conv_expr_descriptor solves this by inserting a
1996 temporary array descriptor. */
1997 gfc_conv_expr_descriptor (&se, e);
c49ea23d 1998
f3b0bb7a
AV
1999 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
2000 || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)));
c49ea23d
PT
2001 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
2002
f3b0bb7a
AV
2003 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)))
2004 {
2005 if (INDIRECT_REF_P (se.expr))
2006 tmp = TREE_OPERAND (se.expr, 0);
2007 else
2008 tmp = se.expr;
2009
2010 gfc_add_modify (&se.pre, sym->backend_decl,
2011 gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp)));
2012 }
2013 else
2014 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
8b704316
PT
2015
2016 if (unlimited)
2017 {
2018 /* Recover the dtype, which has been overwritten by the
2019 assignment from an unlimited polymorphic object. */
2020 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
2021 gfc_add_modify (&se.pre, tmp,
2022 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
2023 }
2024
f3b0bb7a 2025 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
c49ea23d
PT
2026 gfc_finish_block (&se.post));
2027 }
2028
6312ef45
JW
2029 /* Do a scalar pointer assignment; this is for scalar variable targets. */
2030 else if (gfc_is_associate_pointer (sym))
2031 {
2032 gfc_se se;
2033
2034 gcc_assert (!sym->attr.dimension);
2035
2036 gfc_init_se (&se, NULL);
8f75db9f
PT
2037
2038 /* Class associate-names come this way because they are
2039 unconditionally associate pointers and the symbol is scalar. */
2040 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
2041 {
5b384b3d 2042 tree target_expr;
8f75db9f 2043 /* For a class array we need a descriptor for the selector. */
2960a368 2044 gfc_conv_expr_descriptor (&se, e);
5b384b3d
PT
2045 /* Needed to get/set the _len component below. */
2046 target_expr = se.expr;
8f75db9f 2047
8b704316 2048 /* Obtain a temporary class container for the result. */
16e82b25 2049 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
8f75db9f
PT
2050 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
2051
2052 /* Set the offset. */
2053 desc = gfc_class_data_get (se.expr);
2054 offset = gfc_index_zero_node;
2055 for (n = 0; n < e->rank; n++)
2056 {
2057 dim = gfc_rank_cst[n];
2058 tmp = fold_build2_loc (input_location, MULT_EXPR,
2059 gfc_array_index_type,
2060 gfc_conv_descriptor_stride_get (desc, dim),
2061 gfc_conv_descriptor_lbound_get (desc, dim));
2062 offset = fold_build2_loc (input_location, MINUS_EXPR,
2063 gfc_array_index_type,
2064 offset, tmp);
2065 }
5b384b3d
PT
2066 if (need_len_assign)
2067 {
f3b0bb7a
AV
2068 if (e->symtree
2069 && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
d05ccada
PT
2070 && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl)
2071 && TREE_CODE (target_expr) != COMPONENT_REF)
f3b0bb7a
AV
2072 /* Use the original class descriptor stored in the saved
2073 descriptor to get the target_expr. */
2074 target_expr =
2075 GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
2076 else
2077 /* Strip the _data component from the target_expr. */
2078 target_expr = TREE_OPERAND (target_expr, 0);
2079 /* Add a reference to the _len comp to the target expr. */
2080 tmp = gfc_class_len_get (target_expr);
5b384b3d
PT
2081 /* Get the component-ref for the temp structure's _len comp. */
2082 charlen = gfc_class_len_get (se.expr);
026c3cfd 2083 /* Add the assign to the beginning of the block... */
5b384b3d
PT
2084 gfc_add_modify (&se.pre, charlen,
2085 fold_convert (TREE_TYPE (charlen), tmp));
2086 /* and the oposite way at the end of the block, to hand changes
2087 on the string length back. */
2088 gfc_add_modify (&se.post, tmp,
2089 fold_convert (TREE_TYPE (tmp), charlen));
2090 /* Length assignment done, prevent adding it again below. */
2091 need_len_assign = false;
2092 }
8f75db9f
PT
2093 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
2094 }
2095 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
2096 && CLASS_DATA (e)->attr.dimension)
2097 {
2098 /* This is bound to be a class array element. */
2099 gfc_conv_expr_reference (&se, e);
8b704316 2100 /* Get the _vptr component of the class object. */
8f75db9f
PT
2101 tmp = gfc_get_vptr_from_expr (se.expr);
2102 /* Obtain a temporary class container for the result. */
16e82b25 2103 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
8f75db9f 2104 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
fcc4891d 2105 need_len_assign = false;
8f75db9f
PT
2106 }
2107 else
5b384b3d
PT
2108 {
2109 /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign,
2110 which has the string length included. For CHARACTERS it is still
2111 needed and will be done at the end of this routine. */
2112 gfc_conv_expr (&se, e);
2113 need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER;
2114 }
6312ef45 2115
707905d0 2116 if (sym->ts.type == BT_CHARACTER
707905d0
PT
2117 && !sym->attr.select_type_temporary
2118 && VAR_P (sym->ts.u.cl->backend_decl)
2119 && se.string_length != sym->ts.u.cl->backend_decl)
2120 {
2121 gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
f622221a 2122 fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
707905d0
PT
2123 se.string_length));
2124 if (e->expr_type == EXPR_FUNCTION)
2125 {
2126 tmp = gfc_call_free (sym->backend_decl);
2127 gfc_add_expr_to_block (&se.post, tmp);
2128 }
2129 }
2130
707905d0 2131 if (sym->ts.type == BT_CHARACTER && e->ts.type == BT_CHARACTER
b14a13fa 2132 && POINTER_TYPE_P (TREE_TYPE (se.expr)))
707905d0
PT
2133 {
2134 /* These are pointer types already. */
2135 tmp = fold_convert (TREE_TYPE (sym->backend_decl), se.expr);
2136 }
2137 else
2138 {
56b070e3 2139 tree ctree = gfc_get_class_from_expr (se.expr);
75cdd535 2140 tmp = TREE_TYPE (sym->backend_decl);
56b070e3
PT
2141
2142 /* Coarray scalar component expressions can emerge from
2143 the front end as array elements of the _data field. */
2144 if (sym->ts.type == BT_CLASS
2145 && e->ts.type == BT_CLASS && e->rank == 0
2146 && !GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)) && ctree)
2147 {
2148 tree stmp;
2149 tree dtmp;
2150
2151 se.expr = ctree;
2152 dtmp = TREE_TYPE (TREE_TYPE (sym->backend_decl));
2153 ctree = gfc_create_var (dtmp, "class");
2154
2155 stmp = gfc_class_data_get (se.expr);
2156 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (stmp)));
2157
2158 /* Set the fields of the target class variable. */
2159 stmp = gfc_conv_descriptor_data_get (stmp);
2160 dtmp = gfc_class_data_get (ctree);
2161 stmp = fold_convert (TREE_TYPE (dtmp), stmp);
2162 gfc_add_modify (&se.pre, dtmp, stmp);
2163 stmp = gfc_class_vptr_get (se.expr);
2164 dtmp = gfc_class_vptr_get (ctree);
2165 stmp = fold_convert (TREE_TYPE (dtmp), stmp);
2166 gfc_add_modify (&se.pre, dtmp, stmp);
2167 if (UNLIMITED_POLY (sym))
2168 {
2169 stmp = gfc_class_len_get (se.expr);
2170 dtmp = gfc_class_len_get (ctree);
2171 stmp = fold_convert (TREE_TYPE (dtmp), stmp);
2172 gfc_add_modify (&se.pre, dtmp, stmp);
2173 }
2174 se.expr = ctree;
2175 }
75cdd535 2176 tmp = gfc_build_addr_expr (tmp, se.expr);
707905d0
PT
2177 }
2178
6312ef45 2179 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
8b704316 2180
6312ef45
JW
2181 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
2182 gfc_finish_block (&se.post));
2183 }
2184
2185 /* Do a simple assignment. This is for scalar expressions, where we
2186 can simply use expression assignment. */
2187 else
2188 {
2189 gfc_expr *lhs;
0b627b58 2190 tree res;
a8399af8
PT
2191 gfc_se se;
2192
2193 gfc_init_se (&se, NULL);
2194
e53b6e56 2195 /* resolve.cc converts some associate names to allocatable so that
a8399af8
PT
2196 allocation can take place automatically in gfc_trans_assignment.
2197 The frontend prevents them from being either allocated,
2198 deallocated or reallocated. */
2199 if (sym->attr.allocatable)
2200 {
2201 tmp = sym->backend_decl;
2202 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
2203 tmp = gfc_conv_descriptor_data_get (tmp);
2204 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
2205 null_pointer_node));
2206 }
6312ef45
JW
2207
2208 lhs = gfc_lval_expr_from_sym (sym);
0b627b58 2209 res = gfc_trans_assignment (lhs, e, false, true);
a8399af8 2210 gfc_add_expr_to_block (&se.pre, res);
0b627b58
PT
2211
2212 tmp = sym->backend_decl;
2213 if (e->expr_type == EXPR_FUNCTION
2214 && sym->ts.type == BT_DERIVED
2215 && sym->ts.u.derived
2216 && sym->ts.u.derived->attr.pdt_type)
2217 {
2218 tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, tmp,
2219 0);
2220 }
2221 else if (e->expr_type == EXPR_FUNCTION
2222 && sym->ts.type == BT_CLASS
2223 && CLASS_DATA (sym)->ts.u.derived
2224 && CLASS_DATA (sym)->ts.u.derived->attr.pdt_type)
2225 {
2226 tmp = gfc_class_data_get (tmp);
2227 tmp = gfc_deallocate_pdt_comp (CLASS_DATA (sym)->ts.u.derived,
2228 tmp, 0);
2229 }
a8399af8
PT
2230 else if (sym->attr.allocatable)
2231 {
2232 tmp = sym->backend_decl;
2233
2234 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
2235 tmp = gfc_conv_descriptor_data_get (tmp);
2236
2237 /* A simple call to free suffices here. */
2238 tmp = gfc_call_free (tmp);
2239
2240 /* Make sure that reallocation on assignment cannot occur. */
2241 sym->attr.allocatable = 0;
2242 }
2243 else
2244 tmp = NULL_TREE;
0b627b58 2245
a8399af8 2246 res = gfc_finish_block (&se.pre);
0b627b58 2247 gfc_add_init_cleanup (block, res, tmp);
a8399af8 2248 gfc_free_expr (lhs);
6312ef45 2249 }
8b704316 2250
5b384b3d
PT
2251 /* Set the stringlength, when needed. */
2252 if (need_len_assign)
8b704316 2253 {
8b704316
PT
2254 gfc_se se;
2255 gfc_init_se (&se, NULL);
5b384b3d
PT
2256 if (e->symtree->n.sym->ts.type == BT_CHARACTER)
2257 {
707905d0 2258 /* Deferred strings are dealt with in the preceeding. */
5b384b3d
PT
2259 gcc_assert (!e->symtree->n.sym->ts.deferred);
2260 tmp = e->symtree->n.sym->ts.u.cl->backend_decl;
2261 }
6017b8f0 2262 else if (e->symtree->n.sym->attr.function
a7d3cd40 2263 && e->symtree->n.sym == e->symtree->n.sym->result)
6017b8f0
PT
2264 {
2265 tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0);
2266 tmp = gfc_class_len_get (tmp);
2267 }
5b384b3d
PT
2268 else
2269 tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym));
8b704316 2270 gfc_get_symbol_decl (sym);
5b384b3d
PT
2271 charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl
2272 : gfc_class_len_get (sym->backend_decl);
2273 /* Prevent adding a noop len= len. */
2274 if (tmp != charlen)
2275 {
2276 gfc_add_modify (&se.pre, charlen,
2277 fold_convert (TREE_TYPE (charlen), tmp));
2278 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
2279 gfc_finish_block (&se.post));
2280 }
8b704316 2281 }
6312ef45
JW
2282}
2283
2284
9abe5e56
DK
2285/* Translate a BLOCK construct. This is basically what we would do for a
2286 procedure body. */
2287
2288tree
2289gfc_trans_block_construct (gfc_code* code)
2290{
2291 gfc_namespace* ns;
2292 gfc_symbol* sym;
e5ca9693
DK
2293 gfc_wrapped_block block;
2294 tree exit_label;
2295 stmtblock_t body;
6312ef45 2296 gfc_association_list *ass;
9abe5e56 2297
03af1e4c 2298 ns = code->ext.block.ns;
9abe5e56
DK
2299 gcc_assert (ns);
2300 sym = ns->proc_name;
2301 gcc_assert (sym);
2302
e5ca9693 2303 /* Process local variables. */
9abe5e56
DK
2304 gcc_assert (!sym->tlink);
2305 sym->tlink = sym;
6312ef45 2306 gfc_process_block_locals (ns);
9abe5e56 2307
e5ca9693
DK
2308 /* Generate code including exit-label. */
2309 gfc_init_block (&body);
2310 exit_label = gfc_build_label_decl (NULL_TREE);
2311 code->exit_label = exit_label;
41dbbb37 2312
dc7a8b4b 2313 finish_oacc_declare (ns, sym, true);
41dbbb37 2314
e5ca9693
DK
2315 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
2316 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
2317
2318 /* Finish everything. */
2319 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
2320 gfc_trans_deferred_vars (sym, &block);
6312ef45
JW
2321 for (ass = code->ext.block.assoc; ass; ass = ass->next)
2322 trans_associate_var (ass->st->n.sym, &block);
8b704316 2323
e5ca9693 2324 return gfc_finish_wrapped_block (&block);
9abe5e56
DK
2325}
2326
1c122092
ML
2327/* Translate the simple DO construct in a C-style manner.
2328 This is where the loop variable has integer type and step +-1.
2329 Following code will generate infinite loop in case where TO is INT_MAX
2330 (for +1 step) or INT_MIN (for -1 step)
9abe5e56 2331
fbdad37d
PB
2332 We translate a do loop from:
2333
2334 DO dovar = from, to, step
2335 body
2336 END DO
2337
2338 to:
2339
2340 [Evaluate loop bounds and step]
1c122092
ML
2341 dovar = from;
2342 for (;;)
2343 {
2344 if (dovar > to)
2345 goto end_label;
2346 body;
2347 cycle_label:
2348 dovar += step;
fbdad37d 2349 }
1c122092 2350 end_label:
fbdad37d 2351
1c122092
ML
2352 This helps the optimizers by avoiding the extra pre-header condition and
2353 we save a register as we just compare the updated IV (not a value in
2354 previous step). */
fbdad37d
PB
2355
2356static tree
2357gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
bc51e726 2358 tree from, tree to, tree step, tree exit_cond)
fbdad37d
PB
2359{
2360 stmtblock_t body;
2361 tree type;
2362 tree cond;
2363 tree tmp;
33abc845 2364 tree saved_dovar = NULL;
fbdad37d
PB
2365 tree cycle_label;
2366 tree exit_label;
55bd9c35 2367 location_t loc;
fbdad37d 2368 type = TREE_TYPE (dovar);
1c122092 2369 bool is_step_positive = tree_int_cst_sgn (step) > 0;
fbdad37d 2370
9c81750c 2371 loc = gfc_get_location (&code->ext.iterator->start->where);
55bd9c35 2372
fbdad37d 2373 /* Initialize the DO variable: dovar = from. */
8594f636 2374 gfc_add_modify_loc (loc, pblock, dovar,
1c122092 2375 fold_convert (TREE_TYPE (dovar), from));
8b704316 2376
1cc0e193 2377 /* Save value for do-tinkering checking. */
33abc845
TB
2378 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2379 {
2380 saved_dovar = gfc_create_var (type, ".saved_dovar");
55bd9c35 2381 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
33abc845 2382 }
fbdad37d
PB
2383
2384 /* Cycle and exit statements are implemented with gotos. */
2385 cycle_label = gfc_build_label_decl (NULL_TREE);
2386 exit_label = gfc_build_label_decl (NULL_TREE);
2387
1c122092 2388 /* Put the labels where they can be found later. See gfc_trans_do(). */
e5ca9693
DK
2389 code->cycle_label = cycle_label;
2390 code->exit_label = exit_label;
fbdad37d
PB
2391
2392 /* Loop body. */
2393 gfc_start_block (&body);
2394
1c122092
ML
2395 /* Exit the loop if there is an I/O result condition or error. */
2396 if (exit_cond)
2397 {
2398 tmp = build1_v (GOTO_EXPR, exit_label);
2399 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2400 exit_cond, tmp,
2401 build_empty_stmt (loc));
2402 gfc_add_expr_to_block (&body, tmp);
2403 }
2404
2405 /* Evaluate the loop condition. */
2406 if (is_step_positive)
63ee5404 2407 cond = fold_build2_loc (loc, GT_EXPR, logical_type_node, dovar,
1c122092
ML
2408 fold_convert (type, to));
2409 else
63ee5404 2410 cond = fold_build2_loc (loc, LT_EXPR, logical_type_node, dovar,
1c122092
ML
2411 fold_convert (type, to));
2412
2413 cond = gfc_evaluate_now_loc (loc, cond, &body);
170a8bd6
EB
2414 if (code->ext.iterator->unroll && cond != error_mark_node)
2415 cond
2416 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2417 build_int_cst (integer_type_node, annot_expr_unroll_kind),
2418 build_int_cst (integer_type_node, code->ext.iterator->unroll));
1c122092 2419
2bd86b95
HA
2420 if (code->ext.iterator->ivdep && cond != error_mark_node)
2421 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2422 build_int_cst (integer_type_node, annot_expr_ivdep_kind),
2423 integer_zero_node);
2424 if (code->ext.iterator->vector && cond != error_mark_node)
2425 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2426 build_int_cst (integer_type_node, annot_expr_vector_kind),
2427 integer_zero_node);
2428 if (code->ext.iterator->novector && cond != error_mark_node)
2429 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2430 build_int_cst (integer_type_node, annot_expr_no_vector_kind),
2431 integer_zero_node);
2432
1c122092
ML
2433 /* The loop exit. */
2434 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2435 TREE_USED (exit_label) = 1;
2436 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2437 cond, tmp, build_empty_stmt (loc));
2438 gfc_add_expr_to_block (&body, tmp);
2439
2440 /* Check whether the induction variable is equal to INT_MAX
2441 (respectively to INT_MIN). */
2442 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2443 {
2444 tree boundary = is_step_positive ? TYPE_MAX_VALUE (type)
2445 : TYPE_MIN_VALUE (type);
2446
63ee5404 2447 tmp = fold_build2_loc (loc, EQ_EXPR, logical_type_node,
1c122092
ML
2448 dovar, boundary);
2449 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2450 "Loop iterates infinitely");
2451 }
2452
fbdad37d 2453 /* Main loop body. */
bc51e726 2454 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
fbdad37d
PB
2455 gfc_add_expr_to_block (&body, tmp);
2456
2457 /* Label for cycle statements (if needed). */
2458 if (TREE_USED (cycle_label))
2459 {
2460 tmp = build1_v (LABEL_EXPR, cycle_label);
2461 gfc_add_expr_to_block (&body, tmp);
2462 }
2463
1cc0e193 2464 /* Check whether someone has modified the loop variable. */
33abc845
TB
2465 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2466 {
63ee5404 2467 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node,
bc98ed60 2468 dovar, saved_dovar);
33abc845
TB
2469 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2470 "Loop variable has been modified");
2471 }
2472
fbdad37d 2473 /* Increment the loop variable. */
55bd9c35
TB
2474 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2475 gfc_add_modify_loc (loc, &body, dovar, tmp);
fbdad37d 2476
33abc845 2477 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
55bd9c35 2478 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
33abc845 2479
fbdad37d
PB
2480 /* Finish the loop body. */
2481 tmp = gfc_finish_block (&body);
55bd9c35 2482 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
fbdad37d 2483
fbdad37d
PB
2484 gfc_add_expr_to_block (pblock, tmp);
2485
2486 /* Add the exit label. */
2487 tmp = build1_v (LABEL_EXPR, exit_label);
2488 gfc_add_expr_to_block (pblock, tmp);
2489
2490 return gfc_finish_block (pblock);
2491}
2492
6de9cd9a
DN
2493/* Translate the DO construct. This obviously is one of the most
2494 important ones to get right with any compiler, but especially
2495 so for Fortran.
2496
fbdad37d
PB
2497 We special case some loop forms as described in gfc_trans_simple_do.
2498 For other cases we implement them with a separate loop count,
2499 as described in the standard.
6de9cd9a
DN
2500
2501 We translate a do loop from:
2502
2503 DO dovar = from, to, step
2504 body
2505 END DO
2506
2507 to:
2508
fbdad37d 2509 [evaluate loop bounds and step]
5d148c08
FXC
2510 empty = (step > 0 ? to < from : to > from);
2511 countm1 = (to - from) / step;
fbdad37d 2512 dovar = from;
5d148c08 2513 if (empty) goto exit_label;
fbdad37d 2514 for (;;)
6de9cd9a
DN
2515 {
2516 body;
2517cycle_label:
fbdad37d 2518 dovar += step
8c01de7f 2519 countm1t = countm1;
76dac339 2520 countm1--;
8c01de7f 2521 if (countm1t == 0) goto exit_label;
6de9cd9a
DN
2522 }
2523exit_label:
2524
5d148c08
FXC
2525 countm1 is an unsigned integer. It is equal to the loop count minus one,
2526 because the loop count itself can overflow. */
6de9cd9a
DN
2527
2528tree
bc51e726 2529gfc_trans_do (gfc_code * code, tree exit_cond)
6de9cd9a
DN
2530{
2531 gfc_se se;
2532 tree dovar;
33abc845 2533 tree saved_dovar = NULL;
6de9cd9a
DN
2534 tree from;
2535 tree to;
2536 tree step;
5d148c08 2537 tree countm1;
6de9cd9a 2538 tree type;
5d148c08 2539 tree utype;
6de9cd9a
DN
2540 tree cond;
2541 tree cycle_label;
2542 tree exit_label;
2543 tree tmp;
2544 stmtblock_t block;
2545 stmtblock_t body;
55bd9c35 2546 location_t loc;
6de9cd9a
DN
2547
2548 gfc_start_block (&block);
2549
9c81750c 2550 loc = gfc_get_location (&code->ext.iterator->start->where);
55bd9c35 2551
fbdad37d 2552 /* Evaluate all the expressions in the iterator. */
6de9cd9a
DN
2553 gfc_init_se (&se, NULL);
2554 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
2555 gfc_add_block_to_block (&block, &se.pre);
2556 dovar = se.expr;
2557 type = TREE_TYPE (dovar);
2558
2559 gfc_init_se (&se, NULL);
8d5cfa27 2560 gfc_conv_expr_val (&se, code->ext.iterator->start);
6de9cd9a 2561 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 2562 from = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
2563
2564 gfc_init_se (&se, NULL);
8d5cfa27 2565 gfc_conv_expr_val (&se, code->ext.iterator->end);
6de9cd9a 2566 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 2567 to = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
2568
2569 gfc_init_se (&se, NULL);
8d5cfa27 2570 gfc_conv_expr_val (&se, code->ext.iterator->step);
6de9cd9a 2571 gfc_add_block_to_block (&block, &se.pre);
fbdad37d
PB
2572 step = gfc_evaluate_now (se.expr, &block);
2573
33abc845
TB
2574 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2575 {
63ee5404 2576 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, step,
e8160c9a 2577 build_zero_cst (type));
33abc845
TB
2578 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
2579 "DO step value is zero");
2580 }
2581
fbdad37d
PB
2582 /* Special case simple loops. */
2583 if (TREE_CODE (type) == INTEGER_TYPE
2584 && (integer_onep (step)
2585 || tree_int_cst_equal (step, integer_minus_one_node)))
1c122092
ML
2586 return gfc_trans_simple_do (code, &block, dovar, from, to, step,
2587 exit_cond);
6de9cd9a 2588
8d5cfa27 2589 if (TREE_CODE (type) == INTEGER_TYPE)
c0b29099
JJ
2590 utype = unsigned_type_for (type);
2591 else
2592 utype = unsigned_type_for (gfc_array_index_type);
2593 countm1 = gfc_create_var (utype, "countm1");
5d148c08 2594
c0b29099
JJ
2595 /* Cycle and exit statements are implemented with gotos. */
2596 cycle_label = gfc_build_label_decl (NULL_TREE);
2597 exit_label = gfc_build_label_decl (NULL_TREE);
2598 TREE_USED (exit_label) = 1;
2599
e5ca9693
DK
2600 /* Put these labels where they can be found later. */
2601 code->cycle_label = cycle_label;
2602 code->exit_label = exit_label;
2603
c0b29099
JJ
2604 /* Initialize the DO variable: dovar = from. */
2605 gfc_add_modify (&block, dovar, from);
2606
1cc0e193 2607 /* Save value for do-tinkering checking. */
33abc845
TB
2608 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2609 {
2610 saved_dovar = gfc_create_var (type, ".saved_dovar");
55bd9c35 2611 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
33abc845
TB
2612 }
2613
c0b29099
JJ
2614 /* Initialize loop count and jump to exit label if the loop is empty.
2615 This code is executed before we enter the loop body. We generate:
2616 if (step > 0)
2617 {
d17271de 2618 countm1 = (to - from) / step;
8146bb58
TK
2619 if (to < from)
2620 goto exit_label;
c0b29099
JJ
2621 }
2622 else
2623 {
d17271de 2624 countm1 = (from - to) / -step;
8146bb58
TK
2625 if (to > from)
2626 goto exit_label;
2627 }
c5e7e996 2628 */
8146bb58 2629
c0b29099
JJ
2630 if (TREE_CODE (type) == INTEGER_TYPE)
2631 {
c5e7e996 2632 tree pos, neg, tou, fromu, stepu, tmp2;
8146bb58 2633
c5e7e996
RB
2634 /* The distance from FROM to TO cannot always be represented in a signed
2635 type, thus use unsigned arithmetic, also to avoid any undefined
2636 overflow issues. */
2637 tou = fold_convert (utype, to);
2638 fromu = fold_convert (utype, from);
2639 stepu = fold_convert (utype, step);
5d148c08 2640
c5e7e996
RB
2641 /* For a positive step, when to < from, exit, otherwise compute
2642 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
63ee5404 2643 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, to, from);
c5e7e996
RB
2644 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2645 fold_build2_loc (loc, MINUS_EXPR, utype,
2646 tou, fromu),
2647 stepu);
d17271de
RB
2648 pos = build2 (COMPOUND_EXPR, void_type_node,
2649 fold_build2 (MODIFY_EXPR, void_type_node,
2650 countm1, tmp2),
7119f1b1
ML
2651 build3_loc (loc, COND_EXPR, void_type_node,
2652 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
d17271de
RB
2653 build1_loc (loc, GOTO_EXPR, void_type_node,
2654 exit_label), NULL_TREE));
c5e7e996
RB
2655
2656 /* For a negative step, when to > from, exit, otherwise compute
2657 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
63ee5404 2658 tmp = fold_build2_loc (loc, GT_EXPR, logical_type_node, to, from);
c5e7e996
RB
2659 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2660 fold_build2_loc (loc, MINUS_EXPR, utype,
2661 fromu, tou),
2662 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
d17271de
RB
2663 neg = build2 (COMPOUND_EXPR, void_type_node,
2664 fold_build2 (MODIFY_EXPR, void_type_node,
2665 countm1, tmp2),
7119f1b1
ML
2666 build3_loc (loc, COND_EXPR, void_type_node,
2667 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
d17271de
RB
2668 build1_loc (loc, GOTO_EXPR, void_type_node,
2669 exit_label), NULL_TREE));
8146bb58 2670
63ee5404 2671 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, step,
c5e7e996
RB
2672 build_int_cst (TREE_TYPE (step), 0));
2673 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
8146bb58 2674
c0b29099 2675 gfc_add_expr_to_block (&block, tmp);
8d5cfa27
SK
2676 }
2677 else
2678 {
c5e7e996
RB
2679 tree pos_step;
2680
8d5cfa27
SK
2681 /* TODO: We could use the same width as the real type.
2682 This would probably cause more problems that it solves
2683 when we implement "long double" types. */
c0b29099 2684
55bd9c35
TB
2685 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
2686 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
2687 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
c0b29099
JJ
2688 gfc_add_modify (&block, countm1, tmp);
2689
2690 /* We need a special check for empty loops:
2691 empty = (step > 0 ? to < from : to > from); */
63ee5404 2692 pos_step = fold_build2_loc (loc, GT_EXPR, logical_type_node, step,
c5e7e996 2693 build_zero_cst (type));
63ee5404 2694 tmp = fold_build3_loc (loc, COND_EXPR, logical_type_node, pos_step,
55bd9c35 2695 fold_build2_loc (loc, LT_EXPR,
63ee5404 2696 logical_type_node, to, from),
55bd9c35 2697 fold_build2_loc (loc, GT_EXPR,
63ee5404 2698 logical_type_node, to, from));
c0b29099 2699 /* If the loop is empty, go directly to the exit label. */
55bd9c35 2700 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
c0b29099 2701 build1_v (GOTO_EXPR, exit_label),
c2255bc4 2702 build_empty_stmt (input_location));
c0b29099 2703 gfc_add_expr_to_block (&block, tmp);
8d5cfa27 2704 }
5d148c08 2705
6de9cd9a
DN
2706 /* Loop body. */
2707 gfc_start_block (&body);
2708
6de9cd9a 2709 /* Main loop body. */
bc51e726 2710 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
6de9cd9a
DN
2711 gfc_add_expr_to_block (&body, tmp);
2712
2713 /* Label for cycle statements (if needed). */
2714 if (TREE_USED (cycle_label))
2715 {
2716 tmp = build1_v (LABEL_EXPR, cycle_label);
2717 gfc_add_expr_to_block (&body, tmp);
2718 }
2719
1cc0e193 2720 /* Check whether someone has modified the loop variable. */
33abc845
TB
2721 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2722 {
63ee5404 2723 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node, dovar,
bc98ed60 2724 saved_dovar);
33abc845
TB
2725 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2726 "Loop variable has been modified");
2727 }
2728
bc51e726
JD
2729 /* Exit the loop if there is an I/O result condition or error. */
2730 if (exit_cond)
2731 {
2732 tmp = build1_v (GOTO_EXPR, exit_label);
55bd9c35 2733 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
bc98ed60
TB
2734 exit_cond, tmp,
2735 build_empty_stmt (input_location));
bc51e726
JD
2736 gfc_add_expr_to_block (&body, tmp);
2737 }
2738
244974bd 2739 /* Increment the loop variable. */
55bd9c35
TB
2740 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2741 gfc_add_modify_loc (loc, &body, dovar, tmp);
244974bd 2742
33abc845 2743 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
55bd9c35 2744 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
33abc845 2745
8c01de7f
JJ
2746 /* Initialize countm1t. */
2747 tree countm1t = gfc_create_var (utype, "countm1t");
2748 gfc_add_modify_loc (loc, &body, countm1t, countm1);
5d148c08 2749
6de9cd9a 2750 /* Decrement the loop count. */
55bd9c35 2751 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
bc98ed60 2752 build_int_cst (utype, 1));
55bd9c35 2753 gfc_add_modify_loc (loc, &body, countm1, tmp);
6de9cd9a 2754
8c01de7f 2755 /* End with the loop condition. Loop until countm1t == 0. */
63ee5404 2756 cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t,
8c01de7f 2757 build_int_cst (utype, 0));
170a8bd6
EB
2758 if (code->ext.iterator->unroll && cond != error_mark_node)
2759 cond
2760 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2761 build_int_cst (integer_type_node, annot_expr_unroll_kind),
2762 build_int_cst (integer_type_node, code->ext.iterator->unroll));
2bd86b95
HA
2763
2764 if (code->ext.iterator->ivdep && cond != error_mark_node)
2765 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2766 build_int_cst (integer_type_node, annot_expr_ivdep_kind),
2767 integer_zero_node);
2768 if (code->ext.iterator->vector && cond != error_mark_node)
2769 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2770 build_int_cst (integer_type_node, annot_expr_vector_kind),
2771 integer_zero_node);
2772 if (code->ext.iterator->novector && cond != error_mark_node)
2773 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2774 build_int_cst (integer_type_node, annot_expr_no_vector_kind),
2775 integer_zero_node);
2776
8c01de7f
JJ
2777 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2778 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2779 cond, tmp, build_empty_stmt (loc));
2780 gfc_add_expr_to_block (&body, tmp);
2781
6de9cd9a
DN
2782 /* End of loop body. */
2783 tmp = gfc_finish_block (&body);
2784
2785 /* The for loop itself. */
55bd9c35 2786 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
6de9cd9a
DN
2787 gfc_add_expr_to_block (&block, tmp);
2788
2789 /* Add the exit label. */
2790 tmp = build1_v (LABEL_EXPR, exit_label);
2791 gfc_add_expr_to_block (&block, tmp);
2792
2793 return gfc_finish_block (&block);
2794}
2795
2796
2797/* Translate the DO WHILE construct.
2798
2799 We translate
2800
2801 DO WHILE (cond)
2802 body
2803 END DO
2804
2805 to:
2806
2807 for ( ; ; )
2808 {
2809 pre_cond;
2810 if (! cond) goto exit_label;
2811 body;
2812cycle_label:
2813 }
2814exit_label:
2815
2816 Because the evaluation of the exit condition `cond' may have side
2817 effects, we can't do much for empty loop bodies. The backend optimizers
2818 should be smart enough to eliminate any dead loops. */
2819
2820tree
2821gfc_trans_do_while (gfc_code * code)
2822{
2823 gfc_se cond;
2824 tree tmp;
2825 tree cycle_label;
2826 tree exit_label;
2827 stmtblock_t block;
2828
2829 /* Everything we build here is part of the loop body. */
2830 gfc_start_block (&block);
2831
2832 /* Cycle and exit statements are implemented with gotos. */
2833 cycle_label = gfc_build_label_decl (NULL_TREE);
2834 exit_label = gfc_build_label_decl (NULL_TREE);
2835
2836 /* Put the labels where they can be found later. See gfc_trans_do(). */
e5ca9693
DK
2837 code->cycle_label = cycle_label;
2838 code->exit_label = exit_label;
6de9cd9a
DN
2839
2840 /* Create a GIMPLE version of the exit condition. */
2841 gfc_init_se (&cond, NULL);
a513927a 2842 gfc_conv_expr_val (&cond, code->expr1);
6de9cd9a 2843 gfc_add_block_to_block (&block, &cond.pre);
9c81750c
TB
2844 cond.expr = fold_build1_loc (gfc_get_location (&code->expr1->where),
2845 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr),
2846 cond.expr);
6de9cd9a
DN
2847
2848 /* Build "IF (! cond) GOTO exit_label". */
2849 tmp = build1_v (GOTO_EXPR, exit_label);
2850 TREE_USED (exit_label) = 1;
9c81750c 2851 tmp = fold_build3_loc (gfc_get_location (&code->expr1->where), COND_EXPR,
55bd9c35 2852 void_type_node, cond.expr, tmp,
9c81750c
TB
2853 build_empty_stmt (gfc_get_location (
2854 &code->expr1->where)));
6de9cd9a
DN
2855 gfc_add_expr_to_block (&block, tmp);
2856
2857 /* The main body of the loop. */
2858 tmp = gfc_trans_code (code->block->next);
2859 gfc_add_expr_to_block (&block, tmp);
2860
2861 /* Label for cycle statements (if needed). */
2862 if (TREE_USED (cycle_label))
2863 {
2864 tmp = build1_v (LABEL_EXPR, cycle_label);
2865 gfc_add_expr_to_block (&block, tmp);
2866 }
2867
2868 /* End of loop body. */
2869 tmp = gfc_finish_block (&block);
2870
2871 gfc_init_block (&block);
2872 /* Build the loop. */
9c81750c 2873 tmp = fold_build1_loc (gfc_get_location (&code->expr1->where), LOOP_EXPR,
55bd9c35 2874 void_type_node, tmp);
6de9cd9a
DN
2875 gfc_add_expr_to_block (&block, tmp);
2876
2877 /* Add the exit label. */
2878 tmp = build1_v (LABEL_EXPR, exit_label);
2879 gfc_add_expr_to_block (&block, tmp);
2880
2881 return gfc_finish_block (&block);
2882}
2883
2884
dfd6231e
PT
2885/* Deal with the particular case of SELECT_TYPE, where the vtable
2886 addresses are used for the selection. Since these are not sorted,
2887 the selection has to be made by a series of if statements. */
2888
2889static tree
2890gfc_trans_select_type_cases (gfc_code * code)
2891{
2892 gfc_code *c;
2893 gfc_case *cp;
2894 tree tmp;
2895 tree cond;
2896 tree low;
2897 tree high;
2898 gfc_se se;
2899 gfc_se cse;
2900 stmtblock_t block;
2901 stmtblock_t body;
2902 bool def = false;
2903 gfc_expr *e;
2904 gfc_start_block (&block);
2905
2906 /* Calculate the switch expression. */
2907 gfc_init_se (&se, NULL);
2908 gfc_conv_expr_val (&se, code->expr1);
2909 gfc_add_block_to_block (&block, &se.pre);
2910
2911 /* Generate an expression for the selector hash value, for
2912 use to resolve character cases. */
2913 e = gfc_copy_expr (code->expr1->value.function.actual->expr);
2914 gfc_add_hash_component (e);
2915
2916 TREE_USED (code->exit_label) = 0;
2917
2918repeat:
2919 for (c = code->block; c; c = c->block)
2920 {
2921 cp = c->ext.block.case_list;
2922
2923 /* Assume it's the default case. */
2924 low = NULL_TREE;
2925 high = NULL_TREE;
2926 tmp = NULL_TREE;
2927
2928 /* Put the default case at the end. */
2929 if ((!def && !cp->low) || (def && cp->low))
2930 continue;
2931
2932 if (cp->low && (cp->ts.type == BT_CLASS
2933 || cp->ts.type == BT_DERIVED))
2934 {
2935 gfc_init_se (&cse, NULL);
2936 gfc_conv_expr_val (&cse, cp->low);
2937 gfc_add_block_to_block (&block, &cse.pre);
2938 low = cse.expr;
2939 }
2940 else if (cp->ts.type != BT_UNKNOWN)
2941 {
2942 gcc_assert (cp->high);
2943 gfc_init_se (&cse, NULL);
2944 gfc_conv_expr_val (&cse, cp->high);
2945 gfc_add_block_to_block (&block, &cse.pre);
2946 high = cse.expr;
2947 }
2948
2949 gfc_init_block (&body);
2950
2951 /* Add the statements for this case. */
2952 tmp = gfc_trans_code (c->next);
2953 gfc_add_expr_to_block (&body, tmp);
2954
2955 /* Break to the end of the SELECT TYPE construct. The default
2956 case just falls through. */
2957 if (!def)
2958 {
2959 TREE_USED (code->exit_label) = 1;
2960 tmp = build1_v (GOTO_EXPR, code->exit_label);
2961 gfc_add_expr_to_block (&body, tmp);
2962 }
2963
2964 tmp = gfc_finish_block (&body);
2965
2966 if (low != NULL_TREE)
2967 {
2968 /* Compare vtable pointers. */
2969 cond = fold_build2_loc (input_location, EQ_EXPR,
2970 TREE_TYPE (se.expr), se.expr, low);
2971 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2972 cond, tmp,
2973 build_empty_stmt (input_location));
2974 }
2975 else if (high != NULL_TREE)
2976 {
2977 /* Compare hash values for character cases. */
2978 gfc_init_se (&cse, NULL);
2979 gfc_conv_expr_val (&cse, e);
2980 gfc_add_block_to_block (&block, &cse.pre);
2981
2982 cond = fold_build2_loc (input_location, EQ_EXPR,
2983 TREE_TYPE (se.expr), high, cse.expr);
2984 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2985 cond, tmp,
2986 build_empty_stmt (input_location));
2987 }
2988
2989 gfc_add_expr_to_block (&block, tmp);
2990 }
2991
2992 if (!def)
2993 {
2994 def = true;
2995 goto repeat;
2996 }
2997
2998 gfc_free_expr (e);
2999
3000 return gfc_finish_block (&block);
3001}
3002
3003
6de9cd9a
DN
3004/* Translate the SELECT CASE construct for INTEGER case expressions,
3005 without killing all potential optimizations. The problem is that
3006 Fortran allows unbounded cases, but the back-end does not, so we
3007 need to intercept those before we enter the equivalent SWITCH_EXPR
3008 we can build.
3009
3010 For example, we translate this,
3011
3012 SELECT CASE (expr)
3013 CASE (:100,101,105:115)
3014 block_1
3015 CASE (190:199,200:)
3016 block_2
3017 CASE (300)
3018 block_3
3019 CASE DEFAULT
3020 block_4
3021 END SELECT
3022
3023 to the GENERIC equivalent,
3024
3025 switch (expr)
3026 {
3027 case (minimum value for typeof(expr) ... 100:
3028 case 101:
3029 case 105 ... 114:
3030 block1:
3031 goto end_label;
3032
3033 case 200 ... (maximum value for typeof(expr):
3034 case 190 ... 199:
3035 block2;
3036 goto end_label;
3037
3038 case 300:
3039 block_3;
3040 goto end_label;
3041
3042 default:
3043 block_4;
3044 goto end_label;
3045 }
3046
3047 end_label: */
3048
3049static tree
3050gfc_trans_integer_select (gfc_code * code)
3051{
3052 gfc_code *c;
3053 gfc_case *cp;
3054 tree end_label;
3055 tree tmp;
3056 gfc_se se;
3057 stmtblock_t block;
3058 stmtblock_t body;
3059
3060 gfc_start_block (&block);
3061
3062 /* Calculate the switch expression. */
3063 gfc_init_se (&se, NULL);
a513927a 3064 gfc_conv_expr_val (&se, code->expr1);
6de9cd9a
DN
3065 gfc_add_block_to_block (&block, &se.pre);
3066
3067 end_label = gfc_build_label_decl (NULL_TREE);
3068
3069 gfc_init_block (&body);
3070
3071 for (c = code->block; c; c = c->block)
3072 {
29a63d67 3073 for (cp = c->ext.block.case_list; cp; cp = cp->next)
6de9cd9a
DN
3074 {
3075 tree low, high;
3076 tree label;
3077
3078 /* Assume it's the default case. */
3079 low = high = NULL_TREE;
3080
3081 if (cp->low)
3082 {
20585ad6
BM
3083 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
3084 cp->low->ts.kind);
6de9cd9a
DN
3085
3086 /* If there's only a lower bound, set the high bound to the
3087 maximum value of the case expression. */
3088 if (!cp->high)
3089 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
3090 }
3091
3092 if (cp->high)
3093 {
3094 /* Three cases are possible here:
3095
3096 1) There is no lower bound, e.g. CASE (:N).
3097 2) There is a lower bound .NE. high bound, that is
3098 a case range, e.g. CASE (N:M) where M>N (we make
3099 sure that M>N during type resolution).
3100 3) There is a lower bound, and it has the same value
3101 as the high bound, e.g. CASE (N:N). This is our
3102 internal representation of CASE(N).
3103
3104 In the first and second case, we need to set a value for
e2ae1407 3105 high. In the third case, we don't because the GCC middle
6de9cd9a
DN
3106 end represents a single case value by just letting high be
3107 a NULL_TREE. We can't do that because we need to be able
3108 to represent unbounded cases. */
3109
3110 if (!cp->low
b2954e12
SK
3111 || (mpz_cmp (cp->low->value.integer,
3112 cp->high->value.integer) != 0))
20585ad6
BM
3113 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
3114 cp->high->ts.kind);
6de9cd9a
DN
3115
3116 /* Unbounded case. */
3117 if (!cp->low)
3118 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
3119 }
3120
3121 /* Build a label. */
c006df4e 3122 label = gfc_build_label_decl (NULL_TREE);
6de9cd9a
DN
3123
3124 /* Add this case label.
3125 Add parameter 'label', make it match GCC backend. */
3d528853 3126 tmp = build_case_label (low, high, label);
6de9cd9a
DN
3127 gfc_add_expr_to_block (&body, tmp);
3128 }
3129
3130 /* Add the statements for this case. */
3131 tmp = gfc_trans_code (c->next);
3132 gfc_add_expr_to_block (&body, tmp);
3133
3134 /* Break to the end of the construct. */
3135 tmp = build1_v (GOTO_EXPR, end_label);
3136 gfc_add_expr_to_block (&body, tmp);
3137 }
3138
3139 tmp = gfc_finish_block (&body);
9e851845 3140 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, se.expr, tmp);
6de9cd9a
DN
3141 gfc_add_expr_to_block (&block, tmp);
3142
3143 tmp = build1_v (LABEL_EXPR, end_label);
3144 gfc_add_expr_to_block (&block, tmp);
3145
3146 return gfc_finish_block (&block);
3147}
3148
3149
3150/* Translate the SELECT CASE construct for LOGICAL case expressions.
3151
3152 There are only two cases possible here, even though the standard
3153 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
3154 .FALSE., and DEFAULT.
3155
3156 We never generate more than two blocks here. Instead, we always
3157 try to eliminate the DEFAULT case. This way, we can translate this
3158 kind of SELECT construct to a simple
3159
3160 if {} else {};
3161
3162 expression in GENERIC. */
3163
3164static tree
3165gfc_trans_logical_select (gfc_code * code)
3166{
3167 gfc_code *c;
3168 gfc_code *t, *f, *d;
3169 gfc_case *cp;
3170 gfc_se se;
3171 stmtblock_t block;
3172
3173 /* Assume we don't have any cases at all. */
3174 t = f = d = NULL;
3175
3176 /* Now see which ones we actually do have. We can have at most two
3177 cases in a single case list: one for .TRUE. and one for .FALSE.
3178 The default case is always separate. If the cases for .TRUE. and
3179 .FALSE. are in the same case list, the block for that case list
3180 always executed, and we don't generate code a COND_EXPR. */
3181 for (c = code->block; c; c = c->block)
3182 {
29a63d67 3183 for (cp = c->ext.block.case_list; cp; cp = cp->next)
6de9cd9a
DN
3184 {
3185 if (cp->low)
3186 {
3187 if (cp->low->value.logical == 0) /* .FALSE. */
3188 f = c;
3189 else /* if (cp->value.logical != 0), thus .TRUE. */
3190 t = c;
3191 }
3192 else
3193 d = c;
3194 }
3195 }
3196
3197 /* Start a new block. */
3198 gfc_start_block (&block);
3199
3200 /* Calculate the switch expression. We always need to do this
3201 because it may have side effects. */
3202 gfc_init_se (&se, NULL);
a513927a 3203 gfc_conv_expr_val (&se, code->expr1);
6de9cd9a
DN
3204 gfc_add_block_to_block (&block, &se.pre);
3205
3206 if (t == f && t != NULL)
3207 {
3208 /* Cases for .TRUE. and .FALSE. are in the same block. Just
3209 translate the code for these cases, append it to the current
3210 block. */
3211 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
3212 }
3213 else
3214 {
61ead135 3215 tree true_tree, false_tree, stmt;
6de9cd9a 3216
c2255bc4
AH
3217 true_tree = build_empty_stmt (input_location);
3218 false_tree = build_empty_stmt (input_location);
6de9cd9a
DN
3219
3220 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
3221 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
3222 make the missing case the default case. */
3223 if (t != NULL && f != NULL)
3224 d = NULL;
3225 else if (d != NULL)
3226 {
3227 if (t == NULL)
3228 t = d;
3229 else
3230 f = d;
3231 }
3232
3233 /* Translate the code for each of these blocks, and append it to
3234 the current block. */
3235 if (t != NULL)
3236 true_tree = gfc_trans_code (t->next);
3237
3238 if (f != NULL)
3239 false_tree = gfc_trans_code (f->next);
3240
bc98ed60
TB
3241 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3242 se.expr, true_tree, false_tree);
61ead135 3243 gfc_add_expr_to_block (&block, stmt);
6de9cd9a
DN
3244 }
3245
3246 return gfc_finish_block (&block);
3247}
3248
3249
d2886bc7
JJ
3250/* The jump table types are stored in static variables to avoid
3251 constructing them from scratch every single time. */
3252static GTY(()) tree select_struct[2];
3253
6de9cd9a
DN
3254/* Translate the SELECT CASE construct for CHARACTER case expressions.
3255 Instead of generating compares and jumps, it is far simpler to
3256 generate a data structure describing the cases in order and call a
3257 library subroutine that locates the right case.
3258 This is particularly true because this is the only case where we
3259 might have to dispose of a temporary.
3260 The library subroutine returns a pointer to jump to or NULL if no
3261 branches are to be taken. */
3262
3263static tree
3264gfc_trans_character_select (gfc_code *code)
3265{
8748ad99 3266 tree init, end_label, tmp, type, case_num, label, fndecl;
6de9cd9a
DN
3267 stmtblock_t block, body;
3268 gfc_case *cp, *d;
3269 gfc_code *c;
d2886bc7 3270 gfc_se se, expr1se;
d393bbd7 3271 int n, k;
9771b263 3272 vec<constructor_elt, va_gc> *inits = NULL;
d393bbd7 3273
d2886bc7
JJ
3274 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
3275
d393bbd7
FXC
3276 /* The jump table types are stored in static variables to avoid
3277 constructing them from scratch every single time. */
d393bbd7
FXC
3278 static tree ss_string1[2], ss_string1_len[2];
3279 static tree ss_string2[2], ss_string2_len[2];
3280 static tree ss_target[2];
3281
29a63d67 3282 cp = code->block->ext.block.case_list;
d2886bc7
JJ
3283 while (cp->left != NULL)
3284 cp = cp->left;
3285
3286 /* Generate the body */
3287 gfc_start_block (&block);
3288 gfc_init_se (&expr1se, NULL);
3289 gfc_conv_expr_reference (&expr1se, code->expr1);
3290
3291 gfc_add_block_to_block (&block, &expr1se.pre);
3292
3293 end_label = gfc_build_label_decl (NULL_TREE);
3294
3295 gfc_init_block (&body);
3296
3297 /* Attempt to optimize length 1 selects. */
86e033e2 3298 if (integer_onep (expr1se.string_length))
d2886bc7
JJ
3299 {
3300 for (d = cp; d; d = d->right)
3301 {
f622221a 3302 gfc_charlen_t i;
d2886bc7
JJ
3303 if (d->low)
3304 {
3305 gcc_assert (d->low->expr_type == EXPR_CONSTANT
3306 && d->low->ts.type == BT_CHARACTER);
3307 if (d->low->value.character.length > 1)
3308 {
3309 for (i = 1; i < d->low->value.character.length; i++)
3310 if (d->low->value.character.string[i] != ' ')
3311 break;
3312 if (i != d->low->value.character.length)
3313 {
3314 if (optimize && d->high && i == 1)
3315 {
3316 gcc_assert (d->high->expr_type == EXPR_CONSTANT
3317 && d->high->ts.type == BT_CHARACTER);
3318 if (d->high->value.character.length > 1
3319 && (d->low->value.character.string[0]
3320 == d->high->value.character.string[0])
3321 && d->high->value.character.string[1] != ' '
3322 && ((d->low->value.character.string[1] < ' ')
3323 == (d->high->value.character.string[1]
3324 < ' ')))
3325 continue;
3326 }
3327 break;
3328 }
3329 }
3330 }
3331 if (d->high)
3332 {
3333 gcc_assert (d->high->expr_type == EXPR_CONSTANT
3334 && d->high->ts.type == BT_CHARACTER);
3335 if (d->high->value.character.length > 1)
3336 {
3337 for (i = 1; i < d->high->value.character.length; i++)
3338 if (d->high->value.character.string[i] != ' ')
3339 break;
3340 if (i != d->high->value.character.length)
3341 break;
3342 }
3343 }
3344 }
3345 if (d == NULL)
3346 {
3347 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
3348
3349 for (c = code->block; c; c = c->block)
3350 {
29a63d67 3351 for (cp = c->ext.block.case_list; cp; cp = cp->next)
d2886bc7
JJ
3352 {
3353 tree low, high;
3354 tree label;
3355 gfc_char_t r;
3356
3357 /* Assume it's the default case. */
3358 low = high = NULL_TREE;
3359
3360 if (cp->low)
3361 {
3362 /* CASE ('ab') or CASE ('ab':'az') will never match
3363 any length 1 character. */
3364 if (cp->low->value.character.length > 1
3365 && cp->low->value.character.string[1] != ' ')
3366 continue;
3367
3368 if (cp->low->value.character.length > 0)
3369 r = cp->low->value.character.string[0];
3370 else
3371 r = ' ';
3372 low = build_int_cst (ctype, r);
3373
3374 /* If there's only a lower bound, set the high bound
3375 to the maximum value of the case expression. */
3376 if (!cp->high)
3377 high = TYPE_MAX_VALUE (ctype);
3378 }
3379
3380 if (cp->high)
3381 {
3382 if (!cp->low
3383 || (cp->low->value.character.string[0]
3384 != cp->high->value.character.string[0]))
3385 {
3386 if (cp->high->value.character.length > 0)
3387 r = cp->high->value.character.string[0];
3388 else
3389 r = ' ';
3390 high = build_int_cst (ctype, r);
3391 }
3392
3393 /* Unbounded case. */
3394 if (!cp->low)
3395 low = TYPE_MIN_VALUE (ctype);
3396 }
3397
3398 /* Build a label. */
3399 label = gfc_build_label_decl (NULL_TREE);
3400
3401 /* Add this case label.
3402 Add parameter 'label', make it match GCC backend. */
3d528853 3403 tmp = build_case_label (low, high, label);
d2886bc7
JJ
3404 gfc_add_expr_to_block (&body, tmp);
3405 }
3406
3407 /* Add the statements for this case. */
3408 tmp = gfc_trans_code (c->next);
3409 gfc_add_expr_to_block (&body, tmp);
3410
3411 /* Break to the end of the construct. */
3412 tmp = build1_v (GOTO_EXPR, end_label);
3413 gfc_add_expr_to_block (&body, tmp);
3414 }
3415
3416 tmp = gfc_string_to_single_character (expr1se.string_length,
3417 expr1se.expr,
3418 code->expr1->ts.kind);
3419 case_num = gfc_create_var (ctype, "case_num");
3420 gfc_add_modify (&block, case_num, tmp);
3421
3422 gfc_add_block_to_block (&block, &expr1se.post);
3423
3424 tmp = gfc_finish_block (&body);
9e851845
JJ
3425 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
3426 case_num, tmp);
d2886bc7
JJ
3427 gfc_add_expr_to_block (&block, tmp);
3428
3429 tmp = build1_v (LABEL_EXPR, end_label);
3430 gfc_add_expr_to_block (&block, tmp);
3431
3432 return gfc_finish_block (&block);
3433 }
3434 }
6de9cd9a 3435
a513927a 3436 if (code->expr1->ts.kind == 1)
d393bbd7 3437 k = 0;
a513927a 3438 else if (code->expr1->ts.kind == 4)
d393bbd7
FXC
3439 k = 1;
3440 else
3441 gcc_unreachable ();
6de9cd9a 3442
d393bbd7 3443 if (select_struct[k] == NULL)
6de9cd9a 3444 {
dfd6ece2 3445 tree *chain = NULL;
d393bbd7 3446 select_struct[k] = make_node (RECORD_TYPE);
e2cad04b 3447
a513927a 3448 if (code->expr1->ts.kind == 1)
d393bbd7 3449 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
a513927a 3450 else if (code->expr1->ts.kind == 4)
d393bbd7
FXC
3451 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
3452 else
3453 gcc_unreachable ();
6de9cd9a
DN
3454
3455#undef ADD_FIELD
35151cd5
MM
3456#define ADD_FIELD(NAME, TYPE) \
3457 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
3458 get_identifier (stringize(NAME)), \
3459 TYPE, \
3460 &chain)
6de9cd9a 3461
d393bbd7
FXC
3462 ADD_FIELD (string1, pchartype);
3463 ADD_FIELD (string1_len, gfc_charlen_type_node);
6de9cd9a 3464
d393bbd7
FXC
3465 ADD_FIELD (string2, pchartype);
3466 ADD_FIELD (string2_len, gfc_charlen_type_node);
6de9cd9a 3467
dd52ecb0 3468 ADD_FIELD (target, integer_type_node);
6de9cd9a
DN
3469#undef ADD_FIELD
3470
d393bbd7 3471 gfc_finish_type (select_struct[k]);
6de9cd9a
DN
3472 }
3473
6de9cd9a
DN
3474 n = 0;
3475 for (d = cp; d; d = d->right)
3476 d->n = n++;
3477
6de9cd9a
DN
3478 for (c = code->block; c; c = c->block)
3479 {
29a63d67 3480 for (d = c->ext.block.case_list; d; d = d->next)
6de9cd9a 3481 {
2b8327ce 3482 label = gfc_build_label_decl (NULL_TREE);
3d528853
NF
3483 tmp = build_case_label ((d->low == NULL && d->high == NULL)
3484 ? NULL
3485 : build_int_cst (integer_type_node, d->n),
3486 NULL, label);
6de9cd9a
DN
3487 gfc_add_expr_to_block (&body, tmp);
3488 }
3489
3490 tmp = gfc_trans_code (c->next);
3491 gfc_add_expr_to_block (&body, tmp);
3492
923ab88c 3493 tmp = build1_v (GOTO_EXPR, end_label);
6de9cd9a
DN
3494 gfc_add_expr_to_block (&body, tmp);
3495 }
3496
3497 /* Generate the structure describing the branches */
d2886bc7 3498 for (d = cp; d; d = d->right)
6de9cd9a 3499 {
9771b263 3500 vec<constructor_elt, va_gc> *node = NULL;
6de9cd9a
DN
3501
3502 gfc_init_se (&se, NULL);
3503
3504 if (d->low == NULL)
3505 {
8748ad99 3506 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
f622221a 3507 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], build_zero_cst (gfc_charlen_type_node));
6de9cd9a
DN
3508 }
3509 else
3510 {
3511 gfc_conv_expr_reference (&se, d->low);
3512
8748ad99
NF
3513 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
3514 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
6de9cd9a
DN
3515 }
3516
3517 if (d->high == NULL)
3518 {
8748ad99 3519 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
f622221a 3520 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], build_zero_cst (gfc_charlen_type_node));
6de9cd9a
DN
3521 }
3522 else
3523 {
3524 gfc_init_se (&se, NULL);
3525 gfc_conv_expr_reference (&se, d->high);
3526
8748ad99
NF
3527 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
3528 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
6de9cd9a
DN
3529 }
3530
8748ad99
NF
3531 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
3532 build_int_cst (integer_type_node, d->n));
6de9cd9a 3533
8748ad99
NF
3534 tmp = build_constructor (select_struct[k], node);
3535 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
6de9cd9a
DN
3536 }
3537
d393bbd7 3538 type = build_array_type (select_struct[k],
df09d1d5 3539 build_index_type (size_int (n-1)));
6de9cd9a 3540
8748ad99 3541 init = build_constructor (type, inits);
6de9cd9a 3542 TREE_CONSTANT (init) = 1;
6de9cd9a
DN
3543 TREE_STATIC (init) = 1;
3544 /* Create a static variable to hold the jump table. */
3545 tmp = gfc_create_var (type, "jumptable");
3546 TREE_CONSTANT (tmp) = 1;
6de9cd9a 3547 TREE_STATIC (tmp) = 1;
0f0707d1 3548 TREE_READONLY (tmp) = 1;
6de9cd9a
DN
3549 DECL_INITIAL (tmp) = init;
3550 init = tmp;
3551
5039610b 3552 /* Build the library call */
6de9cd9a 3553 init = gfc_build_addr_expr (pvoid_type_node, init);
6de9cd9a 3554
a513927a 3555 if (code->expr1->ts.kind == 1)
d393bbd7 3556 fndecl = gfor_fndecl_select_string;
a513927a 3557 else if (code->expr1->ts.kind == 4)
d393bbd7
FXC
3558 fndecl = gfor_fndecl_select_string_char4;
3559 else
3560 gcc_unreachable ();
3561
db3927fb 3562 tmp = build_call_expr_loc (input_location,
df09d1d5
RG
3563 fndecl, 4, init,
3564 build_int_cst (gfc_charlen_type_node, n),
d2886bc7 3565 expr1se.expr, expr1se.string_length);
dd52ecb0 3566 case_num = gfc_create_var (integer_type_node, "case_num");
726a989a 3567 gfc_add_modify (&block, case_num, tmp);
dc6c7714 3568
d2886bc7 3569 gfc_add_block_to_block (&block, &expr1se.post);
dc6c7714 3570
6de9cd9a 3571 tmp = gfc_finish_block (&body);
9e851845
JJ
3572 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
3573 case_num, tmp);
6de9cd9a 3574 gfc_add_expr_to_block (&block, tmp);
2b8327ce 3575
923ab88c 3576 tmp = build1_v (LABEL_EXPR, end_label);
6de9cd9a
DN
3577 gfc_add_expr_to_block (&block, tmp);
3578
6de9cd9a
DN
3579 return gfc_finish_block (&block);
3580}
3581
3582
3583/* Translate the three variants of the SELECT CASE construct.
3584
3585 SELECT CASEs with INTEGER case expressions can be translated to an
3586 equivalent GENERIC switch statement, and for LOGICAL case
3587 expressions we build one or two if-else compares.
3588
3589 SELECT CASEs with CHARACTER case expressions are a whole different
3590 story, because they don't exist in GENERIC. So we sort them and
3591 do a binary search at runtime.
3592
3593 Fortran has no BREAK statement, and it does not allow jumps from
3594 one case block to another. That makes things a lot easier for
3595 the optimizers. */
3596
3597tree
3598gfc_trans_select (gfc_code * code)
3599{
e5ca9693
DK
3600 stmtblock_t block;
3601 tree body;
3602 tree exit_label;
3603
a513927a 3604 gcc_assert (code && code->expr1);
e5ca9693
DK
3605 gfc_init_block (&block);
3606
3607 /* Build the exit label and hang it in. */
3608 exit_label = gfc_build_label_decl (NULL_TREE);
3609 code->exit_label = exit_label;
6de9cd9a
DN
3610
3611 /* Empty SELECT constructs are legal. */
3612 if (code->block == NULL)
e5ca9693 3613 body = build_empty_stmt (input_location);
6de9cd9a
DN
3614
3615 /* Select the correct translation function. */
e5ca9693
DK
3616 else
3617 switch (code->expr1->ts.type)
3618 {
3619 case BT_LOGICAL:
3620 body = gfc_trans_logical_select (code);
3621 break;
3622
3623 case BT_INTEGER:
3624 body = gfc_trans_integer_select (code);
3625 break;
3626
3627 case BT_CHARACTER:
3628 body = gfc_trans_character_select (code);
3629 break;
3630
3631 default:
3632 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
3633 /* Not reached */
3634 }
3635
3636 /* Build everything together. */
3637 gfc_add_expr_to_block (&block, body);
3638 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3639
dfd6231e
PT
3640 return gfc_finish_block (&block);
3641}
3642
3643tree
3644gfc_trans_select_type (gfc_code * code)
3645{
3646 stmtblock_t block;
3647 tree body;
3648 tree exit_label;
3649
3650 gcc_assert (code && code->expr1);
3651 gfc_init_block (&block);
3652
3653 /* Build the exit label and hang it in. */
3654 exit_label = gfc_build_label_decl (NULL_TREE);
3655 code->exit_label = exit_label;
3656
3657 /* Empty SELECT constructs are legal. */
3658 if (code->block == NULL)
3659 body = build_empty_stmt (input_location);
3660 else
3661 body = gfc_trans_select_type_cases (code);
3662
3663 /* Build everything together. */
3664 gfc_add_expr_to_block (&block, body);
3665
3666 if (TREE_USED (exit_label))
3667 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3668
e5ca9693 3669 return gfc_finish_block (&block);
6de9cd9a
DN
3670}
3671
3672
70570ec1
PT
3673static tree
3674gfc_trans_select_rank_cases (gfc_code * code)
3675{
3676 gfc_code *c;
3677 gfc_case *cp;
3678 tree tmp;
3679 tree cond;
3680 tree low;
70570ec1 3681 tree rank;
70570ec1
PT
3682 gfc_se se;
3683 gfc_se cse;
3684 stmtblock_t block;
3685 stmtblock_t body;
3686 bool def = false;
3687
3688 gfc_start_block (&block);
3689
3690 /* Calculate the switch expression. */
3691 gfc_init_se (&se, NULL);
3692 gfc_conv_expr_descriptor (&se, code->expr1);
3693 rank = gfc_conv_descriptor_rank (se.expr);
3694 rank = gfc_evaluate_now (rank, &block);
64f96237 3695 symbol_attribute attr = gfc_expr_attr (code->expr1);
7f899b23 3696 if (!attr.pointer && !attr.allocatable)
64f96237
TB
3697 {
3698 /* Special case for assumed-rank ('rank(*)', internally -1):
3699 rank = (rank == 0 || ubound[rank-1] != -1) ? rank : -1. */
3700 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3701 rank, build_int_cst (TREE_TYPE (rank), 0));
3702 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3703 fold_convert (gfc_array_index_type, rank),
3704 gfc_index_one_node);
3705 tmp = gfc_conv_descriptor_ubound_get (se.expr, tmp);
3706 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3707 tmp, build_int_cst (TREE_TYPE (tmp), -1));
3708 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3709 logical_type_node, cond, tmp);
3710 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (rank),
3711 cond, rank, build_int_cst (TREE_TYPE (rank), -1));
3712 rank = gfc_evaluate_now (tmp, &block);
3713 }
70570ec1
PT
3714 TREE_USED (code->exit_label) = 0;
3715
3716repeat:
3717 for (c = code->block; c; c = c->block)
3718 {
3719 cp = c->ext.block.case_list;
3720
3721 /* Assume it's the default case. */
3722 low = NULL_TREE;
3723 tmp = NULL_TREE;
3724
3725 /* Put the default case at the end. */
3726 if ((!def && !cp->low) || (def && cp->low))
3727 continue;
3728
3729 if (cp->low)
3730 {
3731 gfc_init_se (&cse, NULL);
3732 gfc_conv_expr_val (&cse, cp->low);
3733 gfc_add_block_to_block (&block, &cse.pre);
3734 low = cse.expr;
3735 }
3736
3737 gfc_init_block (&body);
3738
3739 /* Add the statements for this case. */
3740 tmp = gfc_trans_code (c->next);
3741 gfc_add_expr_to_block (&body, tmp);
3742
3743 /* Break to the end of the SELECT RANK construct. The default
3744 case just falls through. */
3745 if (!def)
3746 {
3747 TREE_USED (code->exit_label) = 1;
3748 tmp = build1_v (GOTO_EXPR, code->exit_label);
3749 gfc_add_expr_to_block (&body, tmp);
3750 }
3751
3752 tmp = gfc_finish_block (&body);
3753
3754 if (low != NULL_TREE)
3755 {
3756 cond = fold_build2_loc (input_location, EQ_EXPR,
64f96237
TB
3757 TREE_TYPE (rank), rank,
3758 fold_convert (TREE_TYPE (rank), low));
70570ec1
PT
3759 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3760 cond, tmp,
3761 build_empty_stmt (input_location));
3762 }
3763
3764 gfc_add_expr_to_block (&block, tmp);
3765 }
3766
3767 if (!def)
3768 {
3769 def = true;
3770 goto repeat;
3771 }
3772
3773 return gfc_finish_block (&block);
3774}
3775
3776
3777tree
3778gfc_trans_select_rank (gfc_code * code)
3779{
3780 stmtblock_t block;
3781 tree body;
3782 tree exit_label;
3783
3784 gcc_assert (code && code->expr1);
3785 gfc_init_block (&block);
3786
3787 /* Build the exit label and hang it in. */
3788 exit_label = gfc_build_label_decl (NULL_TREE);
3789 code->exit_label = exit_label;
3790
3791 /* Empty SELECT constructs are legal. */
3792 if (code->block == NULL)
3793 body = build_empty_stmt (input_location);
3794 else
3795 body = gfc_trans_select_rank_cases (code);
3796
3797 /* Build everything together. */
3798 gfc_add_expr_to_block (&block, body);
3799
3800 if (TREE_USED (exit_label))
3801 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3802
3803 return gfc_finish_block (&block);
3804}
3805
3806
640670c7
PT
3807/* Traversal function to substitute a replacement symtree if the symbol
3808 in the expression is the same as that passed. f == 2 signals that
3809 that variable itself is not to be checked - only the references.
3810 This group of functions is used when the variable expression in a
3811 FORALL assignment has internal references. For example:
3812 FORALL (i = 1:4) p(p(i)) = i
3813 The only recourse here is to store a copy of 'p' for the index
3814 expression. */
3815
3816static gfc_symtree *new_symtree;
3817static gfc_symtree *old_symtree;
3818
3819static bool
3820forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
3821{
908a2235
PT
3822 if (expr->expr_type != EXPR_VARIABLE)
3823 return false;
640670c7
PT
3824
3825 if (*f == 2)
3826 *f = 1;
3827 else if (expr->symtree->n.sym == sym)
3828 expr->symtree = new_symtree;
3829
3830 return false;
3831}
3832
3833static void
3834forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
3835{
3836 gfc_traverse_expr (e, sym, forall_replace, f);
3837}
3838
3839static bool
3840forall_restore (gfc_expr *expr,
3841 gfc_symbol *sym ATTRIBUTE_UNUSED,
3842 int *f ATTRIBUTE_UNUSED)
3843{
908a2235
PT
3844 if (expr->expr_type != EXPR_VARIABLE)
3845 return false;
640670c7
PT
3846
3847 if (expr->symtree == new_symtree)
3848 expr->symtree = old_symtree;
3849
3850 return false;
3851}
3852
3853static void
3854forall_restore_symtree (gfc_expr *e)
3855{
3856 gfc_traverse_expr (e, NULL, forall_restore, 0);
3857}
3858
3859static void
3860forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3861{
3862 gfc_se tse;
3863 gfc_se rse;
3864 gfc_expr *e;
3865 gfc_symbol *new_sym;
3866 gfc_symbol *old_sym;
3867 gfc_symtree *root;
3868 tree tmp;
3869
3870 /* Build a copy of the lvalue. */
a513927a 3871 old_symtree = c->expr1->symtree;
640670c7
PT
3872 old_sym = old_symtree->n.sym;
3873 e = gfc_lval_expr_from_sym (old_sym);
3874 if (old_sym->attr.dimension)
3875 {
3876 gfc_init_se (&tse, NULL);
430f2d1f 3877 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
640670c7
PT
3878 gfc_add_block_to_block (pre, &tse.pre);
3879 gfc_add_block_to_block (post, &tse.post);
db3927fb 3880 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
640670c7 3881
7bd5dad2 3882 if (c->expr1->ref->u.ar.type != AR_SECTION)
640670c7
PT
3883 {
3884 /* Use the variable offset for the temporary. */
568e8e1e
PT
3885 tmp = gfc_conv_array_offset (old_sym->backend_decl);
3886 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
640670c7
PT
3887 }
3888 }
3889 else
3890 {
3891 gfc_init_se (&tse, NULL);
3892 gfc_init_se (&rse, NULL);
3893 gfc_conv_expr (&rse, e);
3894 if (e->ts.type == BT_CHARACTER)
3895 {
3896 tse.string_length = rse.string_length;
3897 tmp = gfc_get_character_type_len (gfc_default_character_kind,
3898 tse.string_length);
3899 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
3900 rse.string_length);
3901 gfc_add_block_to_block (pre, &tse.pre);
3902 gfc_add_block_to_block (post, &tse.post);
3903 }
3904 else
3905 {
3906 tmp = gfc_typenode_for_spec (&e->ts);
3907 tse.expr = gfc_create_var (tmp, "temp");
3908 }
3909
ed673c00
MM
3910 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts,
3911 e->expr_type == EXPR_VARIABLE, false);
640670c7
PT
3912 gfc_add_expr_to_block (pre, tmp);
3913 }
3914 gfc_free_expr (e);
3915
3916 /* Create a new symbol to represent the lvalue. */
3917 new_sym = gfc_new_symbol (old_sym->name, NULL);
3918 new_sym->ts = old_sym->ts;
3919 new_sym->attr.referenced = 1;
59e36b72 3920 new_sym->attr.temporary = 1;
640670c7
PT
3921 new_sym->attr.dimension = old_sym->attr.dimension;
3922 new_sym->attr.flavor = old_sym->attr.flavor;
3923
3924 /* Use the temporary as the backend_decl. */
3925 new_sym->backend_decl = tse.expr;
3926
3927 /* Create a fake symtree for it. */
3928 root = NULL;
3929 new_symtree = gfc_new_symtree (&root, old_sym->name);
3930 new_symtree->n.sym = new_sym;
3931 gcc_assert (new_symtree == root);
3932
3933 /* Go through the expression reference replacing the old_symtree
3934 with the new. */
a513927a 3935 forall_replace_symtree (c->expr1, old_sym, 2);
640670c7
PT
3936
3937 /* Now we have made this temporary, we might as well use it for
3938 the right hand side. */
3939 forall_replace_symtree (c->expr2, old_sym, 1);
3940}
3941
3942
3943/* Handles dependencies in forall assignments. */
3944static int
3945check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3946{
3947 gfc_ref *lref;
3948 gfc_ref *rref;
3949 int need_temp;
3950 gfc_symbol *lsym;
3951
a513927a
SK
3952 lsym = c->expr1->symtree->n.sym;
3953 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
640670c7
PT
3954
3955 /* Now check for dependencies within the 'variable'
3956 expression itself. These are treated by making a complete
3957 copy of variable and changing all the references to it
3958 point to the copy instead. Note that the shallow copy of
3959 the variable will not suffice for derived types with
3960 pointer components. We therefore leave these to their
c09deceb 3961 own devices. Likewise for allocatable components. */
640670c7 3962 if (lsym->ts.type == BT_DERIVED
c09deceb
HA
3963 && (lsym->ts.u.derived->attr.pointer_comp
3964 || lsym->ts.u.derived->attr.alloc_comp))
640670c7
PT
3965 return need_temp;
3966
3967 new_symtree = NULL;
524af0d6 3968 if (find_forall_index (c->expr1, lsym, 2))
640670c7
PT
3969 {
3970 forall_make_variable_temp (c, pre, post);
3971 need_temp = 0;
3972 }
3973
3974 /* Substrings with dependencies are treated in the same
3975 way. */
a513927a
SK
3976 if (c->expr1->ts.type == BT_CHARACTER
3977 && c->expr1->ref
640670c7
PT
3978 && c->expr2->expr_type == EXPR_VARIABLE
3979 && lsym == c->expr2->symtree->n.sym)
3980 {
a513927a 3981 for (lref = c->expr1->ref; lref; lref = lref->next)
640670c7
PT
3982 if (lref->type == REF_SUBSTRING)
3983 break;
3984 for (rref = c->expr2->ref; rref; rref = rref->next)
3985 if (rref->type == REF_SUBSTRING)
3986 break;
3987
3988 if (rref && lref
3989 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
3990 {
3991 forall_make_variable_temp (c, pre, post);
3992 need_temp = 0;
3993 }
3994 }
3995 return need_temp;
3996}
3997
3998
3999static void
4000cleanup_forall_symtrees (gfc_code *c)
4001{
a513927a 4002 forall_restore_symtree (c->expr1);
640670c7 4003 forall_restore_symtree (c->expr2);
cede9502
JM
4004 free (new_symtree->n.sym);
4005 free (new_symtree);
640670c7
PT
4006}
4007
4008
bfcabc6c
RS
4009/* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
4010 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
4011 indicates whether we should generate code to test the FORALLs mask
4012 array. OUTER is the loop header to be used for initializing mask
4013 indices.
4014
4015 The generated loop format is:
6de9cd9a
DN
4016 count = (end - start + step) / step
4017 loopvar = start
4018 while (1)
4019 {
4020 if (count <=0 )
4021 goto end_of_loop
4022 <body>
4023 loopvar += step
4024 count --
4025 }
4026 end_of_loop: */
4027
4028static tree
bfcabc6c
RS
4029gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
4030 int mask_flag, stmtblock_t *outer)
6de9cd9a 4031{
bfcabc6c 4032 int n, nvar;
6de9cd9a
DN
4033 tree tmp;
4034 tree cond;
4035 stmtblock_t block;
4036 tree exit_label;
4037 tree count;
fcf3be37 4038 tree var, start, end, step;
6de9cd9a
DN
4039 iter_info *iter;
4040
bfcabc6c
RS
4041 /* Initialize the mask index outside the FORALL nest. */
4042 if (mask_flag && forall_tmp->mask)
726a989a 4043 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
bfcabc6c 4044
6de9cd9a 4045 iter = forall_tmp->this_loop;
bfcabc6c 4046 nvar = forall_tmp->nvar;
6de9cd9a
DN
4047 for (n = 0; n < nvar; n++)
4048 {
4049 var = iter->var;
4050 start = iter->start;
4051 end = iter->end;
4052 step = iter->step;
4053
4054 exit_label = gfc_build_label_decl (NULL_TREE);
4055 TREE_USED (exit_label) = 1;
4056
4057 /* The loop counter. */
4058 count = gfc_create_var (TREE_TYPE (var), "count");
4059
4060 /* The body of the loop. */
4061 gfc_init_block (&block);
4062
4063 /* The exit condition. */
63ee5404 4064 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
bc98ed60 4065 count, build_int_cst (TREE_TYPE (count), 0));
f0caea48 4066
bc436e10
TK
4067 /* PR 83064 means that we cannot use annot_expr_parallel_kind until
4068 the autoparallelizer can hande this. */
4069 if (forall_tmp->do_concurrent)
ac9effed 4070 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2ca4e2c2 4071 build_int_cst (integer_type_node,
bc436e10 4072 annot_expr_ivdep_kind),
ac9effed 4073 integer_zero_node);
2ca4e2c2 4074
6de9cd9a 4075 tmp = build1_v (GOTO_EXPR, exit_label);
bc98ed60
TB
4076 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4077 cond, tmp, build_empty_stmt (input_location));
6de9cd9a
DN
4078 gfc_add_expr_to_block (&block, tmp);
4079
4080 /* The main loop body. */
4081 gfc_add_expr_to_block (&block, body);
4082
4083 /* Increment the loop variable. */
bc98ed60
TB
4084 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
4085 step);
726a989a 4086 gfc_add_modify (&block, var, tmp);
6de9cd9a 4087
a8e12e4d
TS
4088 /* Advance to the next mask element. Only do this for the
4089 innermost loop. */
fcf3be37
JJ
4090 if (n == 0 && mask_flag && forall_tmp->mask)
4091 {
4092 tree maskindex = forall_tmp->maskindex;
bc98ed60
TB
4093 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4094 maskindex, gfc_index_one_node);
726a989a 4095 gfc_add_modify (&block, maskindex, tmp);
fcf3be37
JJ
4096 }
4097
6de9cd9a 4098 /* Decrement the loop counter. */
bc98ed60
TB
4099 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
4100 build_int_cst (TREE_TYPE (var), 1));
726a989a 4101 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
4102
4103 body = gfc_finish_block (&block);
4104
4105 /* Loop var initialization. */
4106 gfc_init_block (&block);
726a989a 4107 gfc_add_modify (&block, var, start);
6de9cd9a 4108
fcf3be37 4109
6de9cd9a 4110 /* Initialize the loop counter. */
bc98ed60
TB
4111 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
4112 start);
4113 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
4114 tmp);
4115 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
4116 tmp, step);
726a989a 4117 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
4118
4119 /* The loop expression. */
923ab88c 4120 tmp = build1_v (LOOP_EXPR, body);
6de9cd9a
DN
4121 gfc_add_expr_to_block (&block, tmp);
4122
4123 /* The exit label. */
4124 tmp = build1_v (LABEL_EXPR, exit_label);
4125 gfc_add_expr_to_block (&block, tmp);
4126
4127 body = gfc_finish_block (&block);
4128 iter = iter->next;
4129 }
4130 return body;
4131}
4132
4133
bfcabc6c
RS
4134/* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
4135 is nonzero, the body is controlled by all masks in the forall nest.
4136 Otherwise, the innermost loop is not controlled by it's mask. This
4137 is used for initializing that mask. */
6de9cd9a
DN
4138
4139static tree
4140gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
bfcabc6c 4141 int mask_flag)
6de9cd9a
DN
4142{
4143 tree tmp;
bfcabc6c 4144 stmtblock_t header;
6de9cd9a 4145 forall_info *forall_tmp;
bfcabc6c
RS
4146 tree mask, maskindex;
4147
4148 gfc_start_block (&header);
6de9cd9a
DN
4149
4150 forall_tmp = nested_forall_info;
bfcabc6c 4151 while (forall_tmp != NULL)
6de9cd9a 4152 {
bfcabc6c
RS
4153 /* Generate body with masks' control. */
4154 if (mask_flag)
6de9cd9a 4155 {
bfcabc6c
RS
4156 mask = forall_tmp->mask;
4157 maskindex = forall_tmp->maskindex;
6de9cd9a 4158
bfcabc6c
RS
4159 /* If a mask was specified make the assignment conditional. */
4160 if (mask)
4161 {
1d6b7f39 4162 tmp = gfc_build_array_ref (mask, maskindex, NULL);
c2255bc4
AH
4163 body = build3_v (COND_EXPR, tmp, body,
4164 build_empty_stmt (input_location));
6de9cd9a 4165 }
6de9cd9a 4166 }
bfcabc6c 4167 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
e8d366ec 4168 forall_tmp = forall_tmp->prev_nest;
bfcabc6c 4169 mask_flag = 1;
6de9cd9a
DN
4170 }
4171
bfcabc6c
RS
4172 gfc_add_expr_to_block (&header, body);
4173 return gfc_finish_block (&header);
6de9cd9a
DN
4174}
4175
4176
4177/* Allocate data for holding a temporary array. Returns either a local
4178 temporary array or a pointer variable. */
4179
4180static tree
4181gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
4182 tree elem_type)
4183{
4184 tree tmpvar;
4185 tree type;
4186 tree tmp;
6de9cd9a
DN
4187
4188 if (INTEGER_CST_P (size))
bc98ed60
TB
4189 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4190 size, gfc_index_one_node);
6de9cd9a
DN
4191 else
4192 tmp = NULL_TREE;
4193
7ab92584 4194 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
6de9cd9a 4195 type = build_array_type (elem_type, type);
55250ed7 4196 if (gfc_can_put_var_on_stack (bytesize) && INTEGER_CST_P (size))
6de9cd9a 4197 {
6de9cd9a
DN
4198 tmpvar = gfc_create_var (type, "temp");
4199 *pdata = NULL_TREE;
4200 }
4201 else
4202 {
4203 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
4204 *pdata = convert (pvoid_type_node, tmpvar);
4205
1529b8d9 4206 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
726a989a 4207 gfc_add_modify (pblock, tmpvar, tmp);
6de9cd9a
DN
4208 }
4209 return tmpvar;
4210}
4211
4212
4213/* Generate codes to copy the temporary to the actual lhs. */
4214
4215static tree
8de1f441 4216generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
7bd5dad2
LK
4217 tree count1,
4218 gfc_ss *lss, gfc_ss *rss,
4219 tree wheremask, bool invert)
6de9cd9a 4220{
7bd5dad2
LK
4221 stmtblock_t block, body1;
4222 gfc_loopinfo loop;
4223 gfc_se lse;
4224 gfc_se rse;
011daa76 4225 tree tmp;
6de9cd9a
DN
4226 tree wheremaskexpr;
4227
7bd5dad2 4228 (void) rss; /* TODO: unused. */
6de9cd9a 4229
7bd5dad2 4230 gfc_start_block (&block);
6de9cd9a 4231
7bd5dad2
LK
4232 gfc_init_se (&rse, NULL);
4233 gfc_init_se (&lse, NULL);
6de9cd9a 4234
7bd5dad2
LK
4235 if (lss == gfc_ss_terminator)
4236 {
4237 gfc_init_block (&body1);
6de9cd9a 4238 gfc_conv_expr (&lse, expr);
7bd5dad2 4239 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
4240 }
4241 else
4242 {
7bd5dad2
LK
4243 /* Initialize the loop. */
4244 gfc_init_loopinfo (&loop);
6de9cd9a 4245
7bd5dad2
LK
4246 /* We may need LSS to determine the shape of the expression. */
4247 gfc_add_ss_to_loop (&loop, lss);
6de9cd9a 4248
7bd5dad2
LK
4249 gfc_conv_ss_startstride (&loop);
4250 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a
DN
4251
4252 gfc_mark_ss_chain_used (lss, 1);
7bd5dad2
LK
4253 /* Start the loop body. */
4254 gfc_start_scalarized_body (&loop, &body1);
6de9cd9a 4255
7bd5dad2
LK
4256 /* Translate the expression. */
4257 gfc_copy_loopinfo_to_se (&lse, &loop);
6de9cd9a 4258 lse.ss = lss;
7bd5dad2 4259 gfc_conv_expr (&lse, expr);
6de9cd9a
DN
4260
4261 /* Form the expression of the temporary. */
7bd5dad2
LK
4262 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
4263 }
6de9cd9a 4264
7bd5dad2
LK
4265 /* Use the scalar assignment. */
4266 rse.string_length = lse.string_length;
4267 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
4268 expr->expr_type == EXPR_VARIABLE, false);
6de9cd9a 4269
7bd5dad2
LK
4270 /* Form the mask expression according to the mask tree list. */
4271 if (wheremask)
4272 {
4273 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
4274 if (invert)
4275 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4276 TREE_TYPE (wheremaskexpr),
4277 wheremaskexpr);
4278 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4279 wheremaskexpr, tmp,
4280 build_empty_stmt (input_location));
4281 }
6de9cd9a 4282
7bd5dad2 4283 gfc_add_expr_to_block (&body1, tmp);
6de9cd9a 4284
7bd5dad2
LK
4285 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
4286 count1, gfc_index_one_node);
4287 gfc_add_modify (&body1, count1, tmp);
6de9cd9a 4288
7bd5dad2
LK
4289 if (lss == gfc_ss_terminator)
4290 gfc_add_block_to_block (&block, &body1);
4291 else
4292 {
6de9cd9a
DN
4293 /* Increment count3. */
4294 if (count3)
8de1f441 4295 {
bc98ed60 4296 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7bd5dad2
LK
4297 gfc_array_index_type,
4298 count3, gfc_index_one_node);
4299 gfc_add_modify (&body1, count3, tmp);
8de1f441 4300 }
6de9cd9a
DN
4301
4302 /* Generate the copying loops. */
7bd5dad2
LK
4303 gfc_trans_scalarizing_loops (&loop, &body1);
4304
4305 gfc_add_block_to_block (&block, &loop.pre);
4306 gfc_add_block_to_block (&block, &loop.post);
6de9cd9a 4307
7bd5dad2
LK
4308 gfc_cleanup_loop (&loop);
4309 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4310 as tree nodes in SS may not be valid in different scope. */
6de9cd9a 4311 }
7bd5dad2
LK
4312
4313 tmp = gfc_finish_block (&block);
6de9cd9a
DN
4314 return tmp;
4315}
4316
4317
011daa76
RS
4318/* Generate codes to copy rhs to the temporary. TMP1 is the address of
4319 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
4320 and should not be freed. WHEREMASK is the conditional execution mask
4321 whose sense may be inverted by INVERT. */
6de9cd9a
DN
4322
4323static tree
8de1f441
JJ
4324generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
4325 tree count1, gfc_ss *lss, gfc_ss *rss,
011daa76 4326 tree wheremask, bool invert)
6de9cd9a
DN
4327{
4328 stmtblock_t block, body1;
4329 gfc_loopinfo loop;
4330 gfc_se lse;
4331 gfc_se rse;
011daa76 4332 tree tmp;
6de9cd9a
DN
4333 tree wheremaskexpr;
4334
4335 gfc_start_block (&block);
4336
4337 gfc_init_se (&rse, NULL);
4338 gfc_init_se (&lse, NULL);
4339
4340 if (lss == gfc_ss_terminator)
4341 {
4342 gfc_init_block (&body1);
4343 gfc_conv_expr (&rse, expr2);
1d6b7f39 4344 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
4345 }
4346 else
4347 {
1f2959f0 4348 /* Initialize the loop. */
6de9cd9a
DN
4349 gfc_init_loopinfo (&loop);
4350
4351 /* We may need LSS to determine the shape of the expression. */
4352 gfc_add_ss_to_loop (&loop, lss);
4353 gfc_add_ss_to_loop (&loop, rss);
4354
4355 gfc_conv_ss_startstride (&loop);
bdfd2ff0 4356 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
4357
4358 gfc_mark_ss_chain_used (rss, 1);
4359 /* Start the loop body. */
4360 gfc_start_scalarized_body (&loop, &body1);
4361
4362 /* Translate the expression. */
4363 gfc_copy_loopinfo_to_se (&rse, &loop);
4364 rse.ss = rss;
4365 gfc_conv_expr (&rse, expr2);
4366
4367 /* Form the expression of the temporary. */
1d6b7f39 4368 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
4369 }
4370
4371 /* Use the scalar assignment. */
5046aff5 4372 lse.string_length = rse.string_length;
ed673c00
MM
4373 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts,
4374 expr2->expr_type == EXPR_VARIABLE, false);
6de9cd9a
DN
4375
4376 /* Form the mask expression according to the mask tree list. */
4377 if (wheremask)
4378 {
1d6b7f39 4379 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
011daa76 4380 if (invert)
bc98ed60
TB
4381 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4382 TREE_TYPE (wheremaskexpr),
4383 wheremaskexpr);
4384 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4385 wheremaskexpr, tmp,
4386 build_empty_stmt (input_location));
6de9cd9a
DN
4387 }
4388
4389 gfc_add_expr_to_block (&body1, tmp);
4390
4391 if (lss == gfc_ss_terminator)
4392 {
4393 gfc_add_block_to_block (&block, &body1);
8de1f441
JJ
4394
4395 /* Increment count1. */
bc98ed60
TB
4396 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
4397 count1, gfc_index_one_node);
726a989a 4398 gfc_add_modify (&block, count1, tmp);
6de9cd9a
DN
4399 }
4400 else
4401 {
8de1f441 4402 /* Increment count1. */
bc98ed60
TB
4403 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4404 count1, gfc_index_one_node);
726a989a 4405 gfc_add_modify (&body1, count1, tmp);
6de9cd9a
DN
4406
4407 /* Increment count3. */
4408 if (count3)
8de1f441 4409 {
bc98ed60
TB
4410 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4411 gfc_array_index_type,
4412 count3, gfc_index_one_node);
726a989a 4413 gfc_add_modify (&body1, count3, tmp);
8de1f441 4414 }
6de9cd9a
DN
4415
4416 /* Generate the copying loops. */
4417 gfc_trans_scalarizing_loops (&loop, &body1);
4418
4419 gfc_add_block_to_block (&block, &loop.pre);
4420 gfc_add_block_to_block (&block, &loop.post);
4421
4422 gfc_cleanup_loop (&loop);
4423 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
8de1f441 4424 as tree nodes in SS may not be valid in different scope. */
6de9cd9a 4425 }
6de9cd9a
DN
4426
4427 tmp = gfc_finish_block (&block);
4428 return tmp;
4429}
4430
4431
4432/* Calculate the size of temporary needed in the assignment inside forall.
4433 LSS and RSS are filled in this function. */
4434
4435static tree
4436compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
4437 stmtblock_t * pblock,
4438 gfc_ss **lss, gfc_ss **rss)
4439{
4440 gfc_loopinfo loop;
4441 tree size;
4442 int i;
ca86ddcc 4443 int save_flag;
6de9cd9a
DN
4444 tree tmp;
4445
4446 *lss = gfc_walk_expr (expr1);
4447 *rss = NULL;
4448
7ab92584 4449 size = gfc_index_one_node;
6de9cd9a
DN
4450 if (*lss != gfc_ss_terminator)
4451 {
4452 gfc_init_loopinfo (&loop);
4453
4454 /* Walk the RHS of the expression. */
4455 *rss = gfc_walk_expr (expr2);
4456 if (*rss == gfc_ss_terminator)
26f77530
MM
4457 /* The rhs is scalar. Add a ss for the expression. */
4458 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
6de9cd9a
DN
4459
4460 /* Associate the SS with the loop. */
4461 gfc_add_ss_to_loop (&loop, *lss);
4462 /* We don't actually need to add the rhs at this point, but it might
4463 make guessing the loop bounds a bit easier. */
4464 gfc_add_ss_to_loop (&loop, *rss);
4465
4466 /* We only want the shape of the expression, not rest of the junk
4467 generated by the scalarizer. */
4468 loop.array_parameter = 1;
4469
4470 /* Calculate the bounds of the scalarization. */
d3d3011f 4471 save_flag = gfc_option.rtcheck;
c3fb8214 4472 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
6de9cd9a 4473 gfc_conv_ss_startstride (&loop);
d3d3011f 4474 gfc_option.rtcheck = save_flag;
bdfd2ff0 4475 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
4476
4477 /* Figure out how many elements we need. */
4478 for (i = 0; i < loop.dimen; i++)
4479 {
bc98ed60
TB
4480 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4481 gfc_array_index_type,
4482 gfc_index_one_node, loop.from[i]);
4483 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4484 gfc_array_index_type, tmp, loop.to[i]);
4485 size = fold_build2_loc (input_location, MULT_EXPR,
4486 gfc_array_index_type, size, tmp);
6de9cd9a
DN
4487 }
4488 gfc_add_block_to_block (pblock, &loop.pre);
4489 size = gfc_evaluate_now (size, pblock);
4490 gfc_add_block_to_block (pblock, &loop.post);
4491
4492 /* TODO: write a function that cleans up a loopinfo without freeing
4493 the SS chains. Currently a NOP. */
4494 }
4495
4496 return size;
4497}
4498
4499
2ad62c9b
RS
4500/* Calculate the overall iterator number of the nested forall construct.
4501 This routine actually calculates the number of times the body of the
4502 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
4503 that by the expression INNER_SIZE. The BLOCK argument specifies the
4504 block in which to calculate the result, and the optional INNER_SIZE_BODY
4505 argument contains any statements that need to executed (inside the loop)
4506 to initialize or calculate INNER_SIZE. */
6de9cd9a
DN
4507
4508static tree
4509compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
8de1f441 4510 stmtblock_t *inner_size_body, stmtblock_t *block)
6de9cd9a 4511{
2ad62c9b 4512 forall_info *forall_tmp = nested_forall_info;
6de9cd9a
DN
4513 tree tmp, number;
4514 stmtblock_t body;
4515
2ad62c9b
RS
4516 /* We can eliminate the innermost unconditional loops with constant
4517 array bounds. */
3bf783b7
RS
4518 if (INTEGER_CST_P (inner_size))
4519 {
2ad62c9b 4520 while (forall_tmp
8b704316 4521 && !forall_tmp->mask
2ad62c9b 4522 && INTEGER_CST_P (forall_tmp->size))
3bf783b7 4523 {
bc98ed60
TB
4524 inner_size = fold_build2_loc (input_location, MULT_EXPR,
4525 gfc_array_index_type,
4526 inner_size, forall_tmp->size);
2ad62c9b 4527 forall_tmp = forall_tmp->prev_nest;
3bf783b7 4528 }
2ad62c9b
RS
4529
4530 /* If there are no loops left, we have our constant result. */
4531 if (!forall_tmp)
4532 return inner_size;
3bf783b7 4533 }
2ad62c9b
RS
4534
4535 /* Otherwise, create a temporary variable to compute the result. */
6de9cd9a 4536 number = gfc_create_var (gfc_array_index_type, "num");
726a989a 4537 gfc_add_modify (block, number, gfc_index_zero_node);
6de9cd9a
DN
4538
4539 gfc_start_block (&body);
8de1f441
JJ
4540 if (inner_size_body)
4541 gfc_add_block_to_block (&body, inner_size_body);
2ad62c9b 4542 if (forall_tmp)
bc98ed60
TB
4543 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4544 gfc_array_index_type, number, inner_size);
6de9cd9a
DN
4545 else
4546 tmp = inner_size;
726a989a 4547 gfc_add_modify (&body, number, tmp);
6de9cd9a
DN
4548 tmp = gfc_finish_block (&body);
4549
4550 /* Generate loops. */
2ad62c9b
RS
4551 if (forall_tmp != NULL)
4552 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
6de9cd9a
DN
4553
4554 gfc_add_expr_to_block (block, tmp);
4555
4556 return number;
4557}
4558
4559
8de1f441
JJ
4560/* Allocate temporary for forall construct. SIZE is the size of temporary
4561 needed. PTEMP1 is returned for space free. */
6de9cd9a
DN
4562
4563static tree
8de1f441
JJ
4564allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
4565 tree * ptemp1)
6de9cd9a 4566{
bfcabc6c 4567 tree bytesize;
6de9cd9a 4568 tree unit;
6de9cd9a 4569 tree tmp;
6de9cd9a 4570
7c57b2f1 4571 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
bfcabc6c 4572 if (!integer_onep (unit))
bc98ed60
TB
4573 bytesize = fold_build2_loc (input_location, MULT_EXPR,
4574 gfc_array_index_type, size, unit);
bfcabc6c
RS
4575 else
4576 bytesize = size;
6de9cd9a
DN
4577
4578 *ptemp1 = NULL;
bfcabc6c 4579 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
6de9cd9a
DN
4580
4581 if (*ptemp1)
db3927fb 4582 tmp = build_fold_indirect_ref_loc (input_location, tmp);
6de9cd9a
DN
4583 return tmp;
4584}
4585
4586
8de1f441
JJ
4587/* Allocate temporary for forall construct according to the information in
4588 nested_forall_info. INNER_SIZE is the size of temporary needed in the
4589 assignment inside forall. PTEMP1 is returned for space free. */
4590
4591static tree
4592allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
4593 tree inner_size, stmtblock_t * inner_size_body,
4594 stmtblock_t * block, tree * ptemp1)
4595{
4596 tree size;
4597
4598 /* Calculate the total size of temporary needed in forall construct. */
4599 size = compute_overall_iter_number (nested_forall_info, inner_size,
4600 inner_size_body, block);
4601
4602 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
4603}
4604
4605
4606/* Handle assignments inside forall which need temporary.
4607
4608 forall (i=start:end:stride; maskexpr)
4609 e<i> = f<i>
4610 end forall
4611 (where e,f<i> are arbitrary expressions possibly involving i
4612 and there is a dependency between e<i> and f<i>)
4613 Translates to:
4614 masktmp(:) = maskexpr(:)
4615
4616 maskindex = 0;
4617 count1 = 0;
4618 num = 0;
4619 for (i = start; i <= end; i += stride)
4620 num += SIZE (f<i>)
4621 count1 = 0;
4622 ALLOCATE (tmp(num))
4623 for (i = start; i <= end; i += stride)
4624 {
4625 if (masktmp[maskindex++])
4626 tmp[count1++] = f<i>
4627 }
4628 maskindex = 0;
4629 count1 = 0;
4630 for (i = start; i <= end; i += stride)
4631 {
4632 if (masktmp[maskindex++])
4633 e<i> = tmp[count1++]
4634 }
4635 DEALLOCATE (tmp)
4636 */
6de9cd9a 4637static void
011daa76
RS
4638gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4639 tree wheremask, bool invert,
6de9cd9a
DN
4640 forall_info * nested_forall_info,
4641 stmtblock_t * block)
4642{
4643 tree type;
4644 tree inner_size;
4645 gfc_ss *lss, *rss;
8de1f441 4646 tree count, count1;
6de9cd9a
DN
4647 tree tmp, tmp1;
4648 tree ptemp1;
8de1f441 4649 stmtblock_t inner_size_body;
6de9cd9a 4650
8de1f441
JJ
4651 /* Create vars. count1 is the current iterator number of the nested
4652 forall. */
6de9cd9a 4653 count1 = gfc_create_var (gfc_array_index_type, "count1");
6de9cd9a
DN
4654
4655 /* Count is the wheremask index. */
4656 if (wheremask)
4657 {
4658 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 4659 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
4660 }
4661 else
4662 count = NULL;
4663
4664 /* Initialize count1. */
726a989a 4665 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a
DN
4666
4667 /* Calculate the size of temporary needed in the assignment. Return loop, lss
4668 and rss which are used in function generate_loop_for_rhs_to_temp(). */
6de9cd9a 4669 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
7bd5dad2 4670 if (expr1->ts.type == BT_CHARACTER)
640670c7 4671 {
7bd5dad2
LK
4672 type = NULL;
4673 if (expr1->ref && expr1->ref->type == REF_SUBSTRING)
640670c7 4674 {
7bd5dad2
LK
4675 gfc_se ssse;
4676 gfc_init_se (&ssse, NULL);
4677 gfc_conv_expr (&ssse, expr1);
4678 type = gfc_get_character_type_len (gfc_default_character_kind,
4679 ssse.string_length);
4680 }
4681 else
4682 {
4683 if (!expr1->ts.u.cl->backend_decl)
4684 {
4685 gfc_se tse;
4686 gcc_assert (expr1->ts.u.cl->length);
4687 gfc_init_se (&tse, NULL);
4688 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
4689 expr1->ts.u.cl->backend_decl = tse.expr;
4690 }
4691 type = gfc_get_character_type_len (gfc_default_character_kind,
4692 expr1->ts.u.cl->backend_decl);
640670c7 4693 }
640670c7
PT
4694 }
4695 else
4696 type = gfc_typenode_for_spec (&expr1->ts);
6de9cd9a 4697
7bd5dad2
LK
4698 gfc_init_block (&inner_size_body);
4699 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4700 &lss, &rss);
4701
6de9cd9a 4702 /* Allocate temporary for nested forall construct according to the
f7b529fa 4703 information in nested_forall_info and inner_size. */
8de1f441
JJ
4704 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
4705 &inner_size_body, block, &ptemp1);
6de9cd9a 4706
6de9cd9a 4707 /* Generate codes to copy rhs to the temporary . */
8de1f441 4708 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
011daa76 4709 wheremask, invert);
6de9cd9a 4710
1f2959f0 4711 /* Generate body and loops according to the information in
6de9cd9a 4712 nested_forall_info. */
bfcabc6c 4713 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
4714 gfc_add_expr_to_block (block, tmp);
4715
4716 /* Reset count1. */
726a989a 4717 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a 4718
6de9cd9a
DN
4719 /* Reset count. */
4720 if (wheremask)
726a989a 4721 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 4722
7bd5dad2
LK
4723 /* TODO: Second call to compute_inner_temp_size to initialize lss and
4724 rss; there must be a better way. */
4725 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4726 &lss, &rss);
4727
6de9cd9a 4728 /* Generate codes to copy the temporary to lhs. */
011daa76 4729 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
7bd5dad2 4730 lss, rss,
011daa76 4731 wheremask, invert);
6de9cd9a 4732
1f2959f0 4733 /* Generate body and loops according to the information in
6de9cd9a 4734 nested_forall_info. */
bfcabc6c 4735 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
4736 gfc_add_expr_to_block (block, tmp);
4737
4738 if (ptemp1)
4739 {
4740 /* Free the temporary. */
1529b8d9 4741 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
4742 gfc_add_expr_to_block (block, tmp);
4743 }
4744}
4745
4746
4747/* Translate pointer assignment inside FORALL which need temporary. */
4748
4749static void
4750gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4751 forall_info * nested_forall_info,
4752 stmtblock_t * block)
4753{
4754 tree type;
4755 tree inner_size;
4756 gfc_ss *lss, *rss;
4757 gfc_se lse;
4758 gfc_se rse;
6d63e468 4759 gfc_array_info *info;
6de9cd9a
DN
4760 gfc_loopinfo loop;
4761 tree desc;
4762 tree parm;
4763 tree parmtype;
4764 stmtblock_t body;
4765 tree count;
4766 tree tmp, tmp1, ptemp1;
6de9cd9a
DN
4767
4768 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 4769 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 4770
932ebb94 4771 inner_size = gfc_index_one_node;
6de9cd9a
DN
4772 lss = gfc_walk_expr (expr1);
4773 rss = gfc_walk_expr (expr2);
4774 if (lss == gfc_ss_terminator)
4775 {
4776 type = gfc_typenode_for_spec (&expr1->ts);
4777 type = build_pointer_type (type);
4778
4779 /* Allocate temporary for nested forall construct according to the
4780 information in nested_forall_info and inner_size. */
8de1f441
JJ
4781 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
4782 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
4783 gfc_start_block (&body);
4784 gfc_init_se (&lse, NULL);
1d6b7f39 4785 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
4786 gfc_init_se (&rse, NULL);
4787 rse.want_pointer = 1;
4788 gfc_conv_expr (&rse, expr2);
4789 gfc_add_block_to_block (&body, &rse.pre);
726a989a 4790 gfc_add_modify (&body, lse.expr,
cc2804f1 4791 fold_convert (TREE_TYPE (lse.expr), rse.expr));
6de9cd9a
DN
4792 gfc_add_block_to_block (&body, &rse.post);
4793
4794 /* Increment count. */
bc98ed60
TB
4795 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4796 count, gfc_index_one_node);
726a989a 4797 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
4798
4799 tmp = gfc_finish_block (&body);
4800
1f2959f0 4801 /* Generate body and loops according to the information in
6de9cd9a 4802 nested_forall_info. */
bfcabc6c 4803 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
4804 gfc_add_expr_to_block (block, tmp);
4805
4806 /* Reset count. */
726a989a 4807 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 4808
6de9cd9a
DN
4809 gfc_start_block (&body);
4810 gfc_init_se (&lse, NULL);
4811 gfc_init_se (&rse, NULL);
1d6b7f39 4812 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
4813 lse.want_pointer = 1;
4814 gfc_conv_expr (&lse, expr1);
4815 gfc_add_block_to_block (&body, &lse.pre);
726a989a 4816 gfc_add_modify (&body, lse.expr, rse.expr);
6de9cd9a
DN
4817 gfc_add_block_to_block (&body, &lse.post);
4818 /* Increment count. */
bc98ed60
TB
4819 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4820 count, gfc_index_one_node);
726a989a 4821 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
4822 tmp = gfc_finish_block (&body);
4823
1f2959f0 4824 /* Generate body and loops according to the information in
6de9cd9a 4825 nested_forall_info. */
bfcabc6c 4826 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
4827 gfc_add_expr_to_block (block, tmp);
4828 }
4829 else
4830 {
4831 gfc_init_loopinfo (&loop);
4832
4833 /* Associate the SS with the loop. */
4834 gfc_add_ss_to_loop (&loop, rss);
4835
4836 /* Setup the scalarizing loops and bounds. */
4837 gfc_conv_ss_startstride (&loop);
4838
bdfd2ff0 4839 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a 4840
1838afec 4841 info = &rss->info->data.array;
6de9cd9a
DN
4842 desc = info->descriptor;
4843
4844 /* Make a new descriptor. */
4845 parmtype = gfc_get_element_type (TREE_TYPE (desc));
f33beee9 4846 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
fad0afd7 4847 loop.from, loop.to, 1,
10174ddf 4848 GFC_ARRAY_UNKNOWN, true);
6de9cd9a
DN
4849
4850 /* Allocate temporary for nested forall construct. */
4851 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
8de1f441 4852 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
4853 gfc_start_block (&body);
4854 gfc_init_se (&lse, NULL);
1d6b7f39 4855 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a 4856 lse.direct_byref = 1;
2960a368 4857 gfc_conv_expr_descriptor (&lse, expr2);
6de9cd9a
DN
4858
4859 gfc_add_block_to_block (&body, &lse.pre);
4860 gfc_add_block_to_block (&body, &lse.post);
4861
4862 /* Increment count. */
bc98ed60
TB
4863 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4864 count, gfc_index_one_node);
726a989a 4865 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
4866
4867 tmp = gfc_finish_block (&body);
4868
1f2959f0 4869 /* Generate body and loops according to the information in
6de9cd9a 4870 nested_forall_info. */
bfcabc6c 4871 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
4872 gfc_add_expr_to_block (block, tmp);
4873
4874 /* Reset count. */
726a989a 4875 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 4876
1d6b7f39 4877 parm = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a 4878 gfc_init_se (&lse, NULL);
2960a368 4879 gfc_conv_expr_descriptor (&lse, expr1);
726a989a 4880 gfc_add_modify (&lse.pre, lse.expr, parm);
6de9cd9a
DN
4881 gfc_start_block (&body);
4882 gfc_add_block_to_block (&body, &lse.pre);
4883 gfc_add_block_to_block (&body, &lse.post);
4884
4885 /* Increment count. */
bc98ed60
TB
4886 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4887 count, gfc_index_one_node);
726a989a 4888 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
4889
4890 tmp = gfc_finish_block (&body);
4891
bfcabc6c 4892 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
4893 gfc_add_expr_to_block (block, tmp);
4894 }
4895 /* Free the temporary. */
4896 if (ptemp1)
4897 {
1529b8d9 4898 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
4899 gfc_add_expr_to_block (block, tmp);
4900 }
4901}
4902
4903
4904/* FORALL and WHERE statements are really nasty, especially when you nest
4905 them. All the rhs of a forall assignment must be evaluated before the
4906 actual assignments are performed. Presumably this also applies to all the
4907 assignments in an inner where statement. */
4908
4909/* Generate code for a FORALL statement. Any temporaries are allocated as a
4910 linear array, relying on the fact that we process in the same order in all
4911 loops.
4912
4913 forall (i=start:end:stride; maskexpr)
4914 e<i> = f<i>
4915 g<i> = h<i>
4916 end forall
e7dc5b4f 4917 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
6de9cd9a 4918 Translates to:
8de1f441 4919 count = ((end + 1 - start) / stride)
6de9cd9a
DN
4920 masktmp(:) = maskexpr(:)
4921
4922 maskindex = 0;
4923 for (i = start; i <= end; i += stride)
4924 {
4925 if (masktmp[maskindex++])
4926 e<i> = f<i>
4927 }
4928 maskindex = 0;
4929 for (i = start; i <= end; i += stride)
4930 {
4931 if (masktmp[maskindex++])
cafa34aa 4932 g<i> = h<i>
6de9cd9a
DN
4933 }
4934
4935 Note that this code only works when there are no dependencies.
4936 Forall loop with array assignments and data dependencies are a real pain,
4937 because the size of the temporary cannot always be determined before the
1f2959f0 4938 loop is executed. This problem is compounded by the presence of nested
6de9cd9a
DN
4939 FORALL constructs.
4940 */
4941
4942static tree
4943gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
4944{
640670c7
PT
4945 stmtblock_t pre;
4946 stmtblock_t post;
6de9cd9a
DN
4947 stmtblock_t block;
4948 stmtblock_t body;
4949 tree *var;
4950 tree *start;
4951 tree *end;
4952 tree *step;
4953 gfc_expr **varexpr;
4954 tree tmp;
4955 tree assign;
4956 tree size;
6de9cd9a
DN
4957 tree maskindex;
4958 tree mask;
4959 tree pmask;
8c6a85e3 4960 tree cycle_label = NULL_TREE;
6de9cd9a
DN
4961 int n;
4962 int nvar;
4963 int need_temp;
4964 gfc_forall_iterator *fa;
4965 gfc_se se;
4966 gfc_code *c;
7b5b57b7 4967 gfc_saved_var *saved_vars;
bfcabc6c
RS
4968 iter_info *this_forall;
4969 forall_info *info;
e35a0e64
RS
4970 bool need_mask;
4971
4972 /* Do nothing if the mask is false. */
a513927a
SK
4973 if (code->expr1
4974 && code->expr1->expr_type == EXPR_CONSTANT
4975 && !code->expr1->value.logical)
c2255bc4 4976 return build_empty_stmt (input_location);
6de9cd9a
DN
4977
4978 n = 0;
4979 /* Count the FORALL index number. */
4980 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
4981 n++;
4982 nvar = n;
4983
4984 /* Allocate the space for var, start, end, step, varexpr. */
93acb62c
JB
4985 var = XCNEWVEC (tree, nvar);
4986 start = XCNEWVEC (tree, nvar);
4987 end = XCNEWVEC (tree, nvar);
4988 step = XCNEWVEC (tree, nvar);
4989 varexpr = XCNEWVEC (gfc_expr *, nvar);
4990 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
6de9cd9a
DN
4991
4992 /* Allocate the space for info. */
93acb62c 4993 info = XCNEW (forall_info);
bfcabc6c 4994
640670c7
PT
4995 gfc_start_block (&pre);
4996 gfc_init_block (&post);
4997 gfc_init_block (&block);
bfcabc6c 4998
6de9cd9a
DN
4999 n = 0;
5000 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
5001 {
5002 gfc_symbol *sym = fa->var->symtree->n.sym;
5003
bfcabc6c 5004 /* Allocate space for this_forall. */
93acb62c 5005 this_forall = XCNEW (iter_info);
6de9cd9a 5006
6de9cd9a
DN
5007 /* Create a temporary variable for the FORALL index. */
5008 tmp = gfc_typenode_for_spec (&sym->ts);
5009 var[n] = gfc_create_var (tmp, sym->name);
7b5b57b7
PB
5010 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
5011
6de9cd9a
DN
5012 /* Record it in this_forall. */
5013 this_forall->var = var[n];
5014
5015 /* Replace the index symbol's backend_decl with the temporary decl. */
5016 sym->backend_decl = var[n];
5017
5018 /* Work out the start, end and stride for the loop. */
5019 gfc_init_se (&se, NULL);
5020 gfc_conv_expr_val (&se, fa->start);
5021 /* Record it in this_forall. */
5022 this_forall->start = se.expr;
5023 gfc_add_block_to_block (&block, &se.pre);
5024 start[n] = se.expr;
5025
5026 gfc_init_se (&se, NULL);
5027 gfc_conv_expr_val (&se, fa->end);
5028 /* Record it in this_forall. */
5029 this_forall->end = se.expr;
5030 gfc_make_safe_expr (&se);
5031 gfc_add_block_to_block (&block, &se.pre);
5032 end[n] = se.expr;
5033
5034 gfc_init_se (&se, NULL);
5035 gfc_conv_expr_val (&se, fa->stride);
5036 /* Record it in this_forall. */
5037 this_forall->step = se.expr;
5038 gfc_make_safe_expr (&se);
5039 gfc_add_block_to_block (&block, &se.pre);
5040 step[n] = se.expr;
5041
5042 /* Set the NEXT field of this_forall to NULL. */
5043 this_forall->next = NULL;
5044 /* Link this_forall to the info construct. */
bfcabc6c 5045 if (info->this_loop)
6de9cd9a 5046 {
bfcabc6c 5047 iter_info *iter_tmp = info->this_loop;
6de9cd9a
DN
5048 while (iter_tmp->next != NULL)
5049 iter_tmp = iter_tmp->next;
5050 iter_tmp->next = this_forall;
5051 }
bfcabc6c
RS
5052 else
5053 info->this_loop = this_forall;
6de9cd9a
DN
5054
5055 n++;
5056 }
5057 nvar = n;
5058
bfcabc6c 5059 /* Calculate the size needed for the current forall level. */
7ab92584 5060 size = gfc_index_one_node;
6de9cd9a
DN
5061 for (n = 0; n < nvar; n++)
5062 {
6de9cd9a 5063 /* size = (end + step - start) / step. */
8b704316 5064 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
bc98ed60
TB
5065 step[n], start[n]);
5066 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
5067 end[n], tmp);
5068 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
5069 tmp, step[n]);
6de9cd9a
DN
5070 tmp = convert (gfc_array_index_type, tmp);
5071
bc98ed60
TB
5072 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5073 size, tmp);
6de9cd9a
DN
5074 }
5075
5076 /* Record the nvar and size of current forall level. */
5077 info->nvar = nvar;
5078 info->size = size;
5079
a513927a 5080 if (code->expr1)
e35a0e64
RS
5081 {
5082 /* If the mask is .true., consider the FORALL unconditional. */
a513927a
SK
5083 if (code->expr1->expr_type == EXPR_CONSTANT
5084 && code->expr1->value.logical)
e35a0e64
RS
5085 need_mask = false;
5086 else
5087 need_mask = true;
5088 }
5089 else
5090 need_mask = false;
5091
5092 /* First we need to allocate the mask. */
5093 if (need_mask)
bfcabc6c
RS
5094 {
5095 /* As the mask array can be very big, prefer compact boolean types. */
5096 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
5097 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
5098 size, NULL, &block, &pmask);
5099 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
5100
5101 /* Record them in the info structure. */
5102 info->maskindex = maskindex;
5103 info->mask = mask;
5104 }
6de9cd9a
DN
5105 else
5106 {
bfcabc6c
RS
5107 /* No mask was specified. */
5108 maskindex = NULL_TREE;
5109 mask = pmask = NULL_TREE;
5110 }
5111
5112 /* Link the current forall level to nested_forall_info. */
e8d366ec
RS
5113 info->prev_nest = nested_forall_info;
5114 nested_forall_info = info;
6de9cd9a
DN
5115
5116 /* Copy the mask into a temporary variable if required.
f7b529fa 5117 For now we assume a mask temporary is needed. */
e35a0e64 5118 if (need_mask)
6de9cd9a 5119 {
bfcabc6c
RS
5120 /* As the mask array can be very big, prefer compact boolean types. */
5121 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
6de9cd9a 5122
726a989a 5123 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
6de9cd9a
DN
5124
5125 /* Start of mask assignment loop body. */
5126 gfc_start_block (&body);
5127
5128 /* Evaluate the mask expression. */
5129 gfc_init_se (&se, NULL);
a513927a 5130 gfc_conv_expr_val (&se, code->expr1);
6de9cd9a
DN
5131 gfc_add_block_to_block (&body, &se.pre);
5132
5133 /* Store the mask. */
bfcabc6c 5134 se.expr = convert (mask_type, se.expr);
6de9cd9a 5135
1d6b7f39 5136 tmp = gfc_build_array_ref (mask, maskindex, NULL);
726a989a 5137 gfc_add_modify (&body, tmp, se.expr);
6de9cd9a
DN
5138
5139 /* Advance to the next mask element. */
bc98ed60
TB
5140 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5141 maskindex, gfc_index_one_node);
726a989a 5142 gfc_add_modify (&body, maskindex, tmp);
6de9cd9a
DN
5143
5144 /* Generate the loops. */
5145 tmp = gfc_finish_block (&body);
bfcabc6c 5146 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
6de9cd9a
DN
5147 gfc_add_expr_to_block (&block, tmp);
5148 }
6de9cd9a 5149
8c6a85e3
TB
5150 if (code->op == EXEC_DO_CONCURRENT)
5151 {
5152 gfc_init_block (&body);
5153 cycle_label = gfc_build_label_decl (NULL_TREE);
5154 code->cycle_label = cycle_label;
5155 tmp = gfc_trans_code (code->block->next);
5156 gfc_add_expr_to_block (&body, tmp);
5157
5158 if (TREE_USED (cycle_label))
5159 {
5160 tmp = build1_v (LABEL_EXPR, cycle_label);
5161 gfc_add_expr_to_block (&body, tmp);
5162 }
5163
5164 tmp = gfc_finish_block (&body);
2ca4e2c2 5165 nested_forall_info->do_concurrent = true;
8c6a85e3
TB
5166 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
5167 gfc_add_expr_to_block (&block, tmp);
5168 goto done;
5169 }
5170
6de9cd9a
DN
5171 c = code->block->next;
5172
5173 /* TODO: loop merging in FORALL statements. */
5174 /* Now that we've got a copy of the mask, generate the assignment loops. */
5175 while (c)
5176 {
5177 switch (c->op)
5178 {
5179 case EXEC_ASSIGN:
640670c7
PT
5180 /* A scalar or array assignment. DO the simple check for
5181 lhs to rhs dependencies. These make a temporary for the
5182 rhs and form a second forall block to copy to variable. */
5183 need_temp = check_forall_dependencies(c, &pre, &post);
5184
69de3b83 5185 /* Temporaries due to array assignment data dependencies introduce
6de9cd9a 5186 no end of problems. */
7bd5dad2
LK
5187 if (need_temp || flag_test_forall_temp)
5188 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
6de9cd9a
DN
5189 nested_forall_info, &block);
5190 else
5191 {
5192 /* Use the normal assignment copying routines. */
2b56d6a4 5193 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
6de9cd9a 5194
6de9cd9a 5195 /* Generate body and loops. */
bfcabc6c
RS
5196 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
5197 assign, 1);
6de9cd9a
DN
5198 gfc_add_expr_to_block (&block, tmp);
5199 }
5200
640670c7
PT
5201 /* Cleanup any temporary symtrees that have been made to deal
5202 with dependencies. */
5203 if (new_symtree)
5204 cleanup_forall_symtrees (c);
5205
6de9cd9a
DN
5206 break;
5207
5208 case EXEC_WHERE:
6de9cd9a 5209 /* Translate WHERE or WHERE construct nested in FORALL. */
011daa76 5210 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3891cee2 5211 break;
6de9cd9a
DN
5212
5213 /* Pointer assignment inside FORALL. */
5214 case EXEC_POINTER_ASSIGN:
a513927a 5215 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
7bd5dad2
LK
5216 /* Avoid cases where a temporary would never be needed and where
5217 the temp code is guaranteed to fail. */
5218 if (need_temp
5219 || (flag_test_forall_temp
5220 && c->expr2->expr_type != EXPR_CONSTANT
5221 && c->expr2->expr_type != EXPR_NULL))
a513927a 5222 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
6de9cd9a
DN
5223 nested_forall_info, &block);
5224 else
5225 {
5226 /* Use the normal assignment copying routines. */
a513927a 5227 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
6de9cd9a 5228
6de9cd9a 5229 /* Generate body and loops. */
bfcabc6c
RS
5230 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
5231 assign, 1);
6de9cd9a
DN
5232 gfc_add_expr_to_block (&block, tmp);
5233 }
5234 break;
5235
5236 case EXEC_FORALL:
5237 tmp = gfc_trans_forall_1 (c, nested_forall_info);
5238 gfc_add_expr_to_block (&block, tmp);
5239 break;
5240
48474141
PT
5241 /* Explicit subroutine calls are prevented by the frontend but interface
5242 assignments can legitimately produce them. */
476220e7 5243 case EXEC_ASSIGN_CALL:
eb74e79b 5244 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
bfcabc6c 5245 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
48474141
PT
5246 gfc_add_expr_to_block (&block, tmp);
5247 break;
5248
6de9cd9a 5249 default:
6e45f57b 5250 gcc_unreachable ();
6de9cd9a
DN
5251 }
5252
5253 c = c->next;
5254 }
5255
8c6a85e3 5256done:
7b5b57b7
PB
5257 /* Restore the original index variables. */
5258 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
5259 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
6de9cd9a
DN
5260
5261 /* Free the space for var, start, end, step, varexpr. */
cede9502
JM
5262 free (var);
5263 free (start);
5264 free (end);
5265 free (step);
5266 free (varexpr);
5267 free (saved_vars);
6de9cd9a 5268
3231fe90
MM
5269 for (this_forall = info->this_loop; this_forall;)
5270 {
5271 iter_info *next = this_forall->next;
cede9502 5272 free (this_forall);
3231fe90
MM
5273 this_forall = next;
5274 }
5275
e8d366ec 5276 /* Free the space for this forall_info. */
cede9502 5277 free (info);
e8d366ec 5278
6de9cd9a
DN
5279 if (pmask)
5280 {
5281 /* Free the temporary for the mask. */
1529b8d9 5282 tmp = gfc_call_free (pmask);
6de9cd9a
DN
5283 gfc_add_expr_to_block (&block, tmp);
5284 }
5285 if (maskindex)
5286 pushdecl (maskindex);
5287
640670c7
PT
5288 gfc_add_block_to_block (&pre, &block);
5289 gfc_add_block_to_block (&pre, &post);
5290
5291 return gfc_finish_block (&pre);
6de9cd9a
DN
5292}
5293
5294
5295/* Translate the FORALL statement or construct. */
5296
5297tree gfc_trans_forall (gfc_code * code)
5298{
5299 return gfc_trans_forall_1 (code, NULL);
5300}
5301
5302
8c6a85e3
TB
5303/* Translate the DO CONCURRENT construct. */
5304
5305tree gfc_trans_do_concurrent (gfc_code * code)
5306{
5307 return gfc_trans_forall_1 (code, NULL);
5308}
5309
5310
6de9cd9a
DN
5311/* Evaluate the WHERE mask expression, copy its value to a temporary.
5312 If the WHERE construct is nested in FORALL, compute the overall temporary
5313 needed by the WHERE mask expression multiplied by the iterator number of
5314 the nested forall.
5315 ME is the WHERE mask expression.
011daa76
RS
5316 MASK is the current execution mask upon input, whose sense may or may
5317 not be inverted as specified by the INVERT argument.
3891cee2
RS
5318 CMASK is the updated execution mask on output, or NULL if not required.
5319 PMASK is the pending execution mask on output, or NULL if not required.
5320 BLOCK is the block in which to place the condition evaluation loops. */
6de9cd9a 5321
3891cee2 5322static void
6de9cd9a 5323gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
011daa76 5324 tree mask, bool invert, tree cmask, tree pmask,
3891cee2 5325 tree mask_type, stmtblock_t * block)
6de9cd9a
DN
5326{
5327 tree tmp, tmp1;
5328 gfc_ss *lss, *rss;
5329 gfc_loopinfo loop;
3891cee2
RS
5330 stmtblock_t body, body1;
5331 tree count, cond, mtmp;
6de9cd9a 5332 gfc_se lse, rse;
6de9cd9a
DN
5333
5334 gfc_init_loopinfo (&loop);
5335
3891cee2
RS
5336 lss = gfc_walk_expr (me);
5337 rss = gfc_walk_expr (me);
6de9cd9a
DN
5338
5339 /* Variable to index the temporary. */
5340 count = gfc_create_var (gfc_array_index_type, "count");
1f2959f0 5341 /* Initialize count. */
726a989a 5342 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
5343
5344 gfc_start_block (&body);
5345
5346 gfc_init_se (&rse, NULL);
5347 gfc_init_se (&lse, NULL);
5348
5349 if (lss == gfc_ss_terminator)
5350 {
5351 gfc_init_block (&body1);
5352 }
5353 else
5354 {
1f2959f0 5355 /* Initialize the loop. */
6de9cd9a
DN
5356 gfc_init_loopinfo (&loop);
5357
5358 /* We may need LSS to determine the shape of the expression. */
5359 gfc_add_ss_to_loop (&loop, lss);
5360 gfc_add_ss_to_loop (&loop, rss);
5361
5362 gfc_conv_ss_startstride (&loop);
bdfd2ff0 5363 gfc_conv_loop_setup (&loop, &me->where);
6de9cd9a
DN
5364
5365 gfc_mark_ss_chain_used (rss, 1);
5366 /* Start the loop body. */
5367 gfc_start_scalarized_body (&loop, &body1);
5368
5369 /* Translate the expression. */
5370 gfc_copy_loopinfo_to_se (&rse, &loop);
5371 rse.ss = rss;
5372 gfc_conv_expr (&rse, me);
5373 }
6de9cd9a 5374
b82feea5 5375 /* Variable to evaluate mask condition. */
3891cee2
RS
5376 cond = gfc_create_var (mask_type, "cond");
5377 if (mask && (cmask || pmask))
5378 mtmp = gfc_create_var (mask_type, "mask");
5379 else mtmp = NULL_TREE;
5380
5381 gfc_add_block_to_block (&body1, &lse.pre);
5382 gfc_add_block_to_block (&body1, &rse.pre);
6de9cd9a 5383
726a989a 5384 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
3891cee2
RS
5385
5386 if (mask && (cmask || pmask))
42e73749 5387 {
1d6b7f39 5388 tmp = gfc_build_array_ref (mask, count, NULL);
011daa76 5389 if (invert)
bc98ed60 5390 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
726a989a 5391 gfc_add_modify (&body1, mtmp, tmp);
42e73749 5392 }
6de9cd9a 5393
3891cee2
RS
5394 if (cmask)
5395 {
1d6b7f39 5396 tmp1 = gfc_build_array_ref (cmask, count, NULL);
3891cee2
RS
5397 tmp = cond;
5398 if (mask)
bc98ed60
TB
5399 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
5400 mtmp, tmp);
726a989a 5401 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
5402 }
5403
5404 if (pmask)
5405 {
1d6b7f39 5406 tmp1 = gfc_build_array_ref (pmask, count, NULL);
bc98ed60 5407 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
3891cee2 5408 if (mask)
bc98ed60
TB
5409 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
5410 tmp);
726a989a 5411 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
5412 }
5413
5414 gfc_add_block_to_block (&body1, &lse.post);
5415 gfc_add_block_to_block (&body1, &rse.post);
5416
5417 if (lss == gfc_ss_terminator)
6de9cd9a
DN
5418 {
5419 gfc_add_block_to_block (&body, &body1);
5420 }
5421 else
5422 {
5423 /* Increment count. */
bc98ed60
TB
5424 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5425 count, gfc_index_one_node);
726a989a 5426 gfc_add_modify (&body1, count, tmp1);
6de9cd9a
DN
5427
5428 /* Generate the copying loops. */
5429 gfc_trans_scalarizing_loops (&loop, &body1);
5430
5431 gfc_add_block_to_block (&body, &loop.pre);
5432 gfc_add_block_to_block (&body, &loop.post);
5433
5434 gfc_cleanup_loop (&loop);
5435 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
5436 as tree nodes in SS may not be valid in different scope. */
5437 }
5438
5439 tmp1 = gfc_finish_block (&body);
5440 /* If the WHERE construct is inside FORALL, fill the full temporary. */
5441 if (nested_forall_info != NULL)
bfcabc6c 5442 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
6de9cd9a
DN
5443
5444 gfc_add_expr_to_block (block, tmp1);
6de9cd9a
DN
5445}
5446
5447
5448/* Translate an assignment statement in a WHERE statement or construct
5449 statement. The MASK expression is used to control which elements
011daa76
RS
5450 of EXPR1 shall be assigned. The sense of MASK is specified by
5451 INVERT. */
6de9cd9a
DN
5452
5453static tree
011daa76
RS
5454gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
5455 tree mask, bool invert,
a00b8d1a 5456 tree count1, tree count2,
eb74e79b 5457 gfc_code *cnext)
6de9cd9a
DN
5458{
5459 gfc_se lse;
5460 gfc_se rse;
5461 gfc_ss *lss;
5462 gfc_ss *lss_section;
5463 gfc_ss *rss;
5464
5465 gfc_loopinfo loop;
5466 tree tmp;
5467 stmtblock_t block;
5468 stmtblock_t body;
3c90c9ae 5469 tree index, maskexpr;
6de9cd9a 5470
1cc0e193 5471 /* A defined assignment. */
eb74e79b
PT
5472 if (cnext && cnext->resolved_sym)
5473 return gfc_trans_call (cnext, true, mask, count1, invert);
5474
6de9cd9a
DN
5475#if 0
5476 /* TODO: handle this special case.
5477 Special case a single function returning an array. */
5478 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
5479 {
5480 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
5481 if (tmp)
5482 return tmp;
5483 }
5484#endif
5485
5486 /* Assignment of the form lhs = rhs. */
5487 gfc_start_block (&block);
5488
5489 gfc_init_se (&lse, NULL);
5490 gfc_init_se (&rse, NULL);
5491
5492 /* Walk the lhs. */
5493 lss = gfc_walk_expr (expr1);
5494 rss = NULL;
5495
5496 /* In each where-assign-stmt, the mask-expr and the variable being
5497 defined shall be arrays of the same shape. */
6e45f57b 5498 gcc_assert (lss != gfc_ss_terminator);
6de9cd9a
DN
5499
5500 /* The assignment needs scalarization. */
5501 lss_section = lss;
5502
5503 /* Find a non-scalar SS from the lhs. */
5504 while (lss_section != gfc_ss_terminator
bcc4d4e0 5505 && lss_section->info->type != GFC_SS_SECTION)
6de9cd9a
DN
5506 lss_section = lss_section->next;
5507
6e45f57b 5508 gcc_assert (lss_section != gfc_ss_terminator);
6de9cd9a
DN
5509
5510 /* Initialize the scalarizer. */
5511 gfc_init_loopinfo (&loop);
5512
5513 /* Walk the rhs. */
5514 rss = gfc_walk_expr (expr2);
5515 if (rss == gfc_ss_terminator)
26f77530
MM
5516 {
5517 /* The rhs is scalar. Add a ss for the expression. */
5518 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
42d0058e 5519 rss->info->where = 1;
6de9cd9a
DN
5520 }
5521
5522 /* Associate the SS with the loop. */
5523 gfc_add_ss_to_loop (&loop, lss);
5524 gfc_add_ss_to_loop (&loop, rss);
5525
5526 /* Calculate the bounds of the scalarization. */
5527 gfc_conv_ss_startstride (&loop);
5528
5529 /* Resolve any data dependencies in the statement. */
5530 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
5531
5532 /* Setup the scalarizing loops. */
bdfd2ff0 5533 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
5534
5535 /* Setup the gfc_se structures. */
5536 gfc_copy_loopinfo_to_se (&lse, &loop);
5537 gfc_copy_loopinfo_to_se (&rse, &loop);
5538
5539 rse.ss = rss;
5540 gfc_mark_ss_chain_used (rss, 1);
5541 if (loop.temp_ss == NULL)
5542 {
5543 lse.ss = lss;
5544 gfc_mark_ss_chain_used (lss, 1);
5545 }
5546 else
5547 {
5548 lse.ss = loop.temp_ss;
5549 gfc_mark_ss_chain_used (lss, 3);
5550 gfc_mark_ss_chain_used (loop.temp_ss, 3);
5551 }
5552
5553 /* Start the scalarized loop body. */
5554 gfc_start_scalarized_body (&loop, &body);
5555
5556 /* Translate the expression. */
5557 gfc_conv_expr (&rse, expr2);
5558 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
3db5d687 5559 gfc_conv_tmp_array_ref (&lse);
6de9cd9a
DN
5560 else
5561 gfc_conv_expr (&lse, expr1);
5562
3c90c9ae 5563 /* Form the mask expression according to the mask. */
6de9cd9a 5564 index = count1;
1d6b7f39 5565 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76 5566 if (invert)
bc98ed60
TB
5567 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
5568 TREE_TYPE (maskexpr), maskexpr);
6de9cd9a 5569
6de9cd9a 5570 /* Use the scalar assignment as is. */
eb74e79b 5571 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
ed673c00 5572 false, loop.temp_ss == NULL);
a00b8d1a 5573
c2255bc4 5574 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
6de9cd9a
DN
5575
5576 gfc_add_expr_to_block (&body, tmp);
5577
5578 if (lss == gfc_ss_terminator)
5579 {
5580 /* Increment count1. */
bc98ed60
TB
5581 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5582 count1, gfc_index_one_node);
726a989a 5583 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
5584
5585 /* Use the scalar assignment as is. */
5586 gfc_add_block_to_block (&block, &body);
5587 }
5588 else
5589 {
6e45f57b
PB
5590 gcc_assert (lse.ss == gfc_ss_terminator
5591 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
5592
5593 if (loop.temp_ss != NULL)
5594 {
5595 /* Increment count1 before finish the main body of a scalarized
5596 expression. */
bc98ed60
TB
5597 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5598 gfc_array_index_type, count1, gfc_index_one_node);
726a989a 5599 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
5600 gfc_trans_scalarized_loop_boundary (&loop, &body);
5601
5602 /* We need to copy the temporary to the actual lhs. */
5603 gfc_init_se (&lse, NULL);
5604 gfc_init_se (&rse, NULL);
5605 gfc_copy_loopinfo_to_se (&lse, &loop);
5606 gfc_copy_loopinfo_to_se (&rse, &loop);
5607
5608 rse.ss = loop.temp_ss;
5609 lse.ss = lss;
5610
5611 gfc_conv_tmp_array_ref (&rse);
6de9cd9a
DN
5612 gfc_conv_expr (&lse, expr1);
5613
6e45f57b
PB
5614 gcc_assert (lse.ss == gfc_ss_terminator
5615 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
5616
5617 /* Form the mask expression according to the mask tree list. */
5618 index = count2;
1d6b7f39 5619 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76 5620 if (invert)
bc98ed60
TB
5621 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
5622 TREE_TYPE (maskexpr), maskexpr);
6de9cd9a 5623
6de9cd9a 5624 /* Use the scalar assignment as is. */
ed673c00 5625 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, true);
c2255bc4
AH
5626 tmp = build3_v (COND_EXPR, maskexpr, tmp,
5627 build_empty_stmt (input_location));
6de9cd9a 5628 gfc_add_expr_to_block (&body, tmp);
7ab92584 5629
6de9cd9a 5630 /* Increment count2. */
bc98ed60
TB
5631 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5632 gfc_array_index_type, count2,
5633 gfc_index_one_node);
726a989a 5634 gfc_add_modify (&body, count2, tmp);
6de9cd9a
DN
5635 }
5636 else
5637 {
5638 /* Increment count1. */
bc98ed60
TB
5639 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5640 gfc_array_index_type, count1,
5641 gfc_index_one_node);
726a989a 5642 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
5643 }
5644
5645 /* Generate the copying loops. */
5646 gfc_trans_scalarizing_loops (&loop, &body);
5647
5648 /* Wrap the whole thing up. */
5649 gfc_add_block_to_block (&block, &loop.pre);
5650 gfc_add_block_to_block (&block, &loop.post);
5651 gfc_cleanup_loop (&loop);
5652 }
5653
5654 return gfc_finish_block (&block);
5655}
5656
5657
5658/* Translate the WHERE construct or statement.
aa9c57ec 5659 This function can be called iteratively to translate the nested WHERE
6de9cd9a 5660 construct or statement.
3891cee2 5661 MASK is the control mask. */
6de9cd9a
DN
5662
5663static void
011daa76 5664gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
3891cee2 5665 forall_info * nested_forall_info, stmtblock_t * block)
6de9cd9a 5666{
3891cee2
RS
5667 stmtblock_t inner_size_body;
5668 tree inner_size, size;
5669 gfc_ss *lss, *rss;
5670 tree mask_type;
6de9cd9a
DN
5671 gfc_expr *expr1;
5672 gfc_expr *expr2;
5673 gfc_code *cblock;
5674 gfc_code *cnext;
3891cee2 5675 tree tmp;
ae772c2d 5676 tree cond;
6de9cd9a 5677 tree count1, count2;
011daa76
RS
5678 bool need_cmask;
5679 bool need_pmask;
6de9cd9a 5680 int need_temp;
3891cee2
RS
5681 tree pcmask = NULL_TREE;
5682 tree ppmask = NULL_TREE;
5683 tree cmask = NULL_TREE;
5684 tree pmask = NULL_TREE;
a00b8d1a 5685 gfc_actual_arglist *arg;
6de9cd9a
DN
5686
5687 /* the WHERE statement or the WHERE construct statement. */
5688 cblock = code->block;
3891cee2 5689
3891cee2
RS
5690 /* As the mask array can be very big, prefer compact boolean types. */
5691 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
5692
011daa76
RS
5693 /* Determine which temporary masks are needed. */
5694 if (!cblock->block)
90f58ec8 5695 {
011daa76
RS
5696 /* One clause: No ELSEWHEREs. */
5697 need_cmask = (cblock->next != 0);
5698 need_pmask = false;
90f58ec8 5699 }
011daa76 5700 else if (cblock->block->block)
90f58ec8 5701 {
011daa76
RS
5702 /* Three or more clauses: Conditional ELSEWHEREs. */
5703 need_cmask = true;
5704 need_pmask = true;
90f58ec8 5705 }
011daa76
RS
5706 else if (cblock->next)
5707 {
5708 /* Two clauses, the first non-empty. */
5709 need_cmask = true;
5710 need_pmask = (mask != NULL_TREE
5711 && cblock->block->next != 0);
5712 }
5713 else if (!cblock->block->next)
3891cee2 5714 {
011daa76
RS
5715 /* Two clauses, both empty. */
5716 need_cmask = false;
5717 need_pmask = false;
5718 }
5719 /* Two clauses, the first empty, the second non-empty. */
5720 else if (mask)
5721 {
a513927a 5722 need_cmask = (cblock->block->expr1 != 0);
011daa76 5723 need_pmask = true;
3891cee2
RS
5724 }
5725 else
5726 {
011daa76
RS
5727 need_cmask = true;
5728 need_pmask = false;
5729 }
5730
5731 if (need_cmask || need_pmask)
5732 {
5733 /* Calculate the size of temporary needed by the mask-expr. */
5734 gfc_init_block (&inner_size_body);
a513927a 5735 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
011daa76
RS
5736 &inner_size_body, &lss, &rss);
5737
fcba5509
MM
5738 gfc_free_ss_chain (lss);
5739 gfc_free_ss_chain (rss);
5740
011daa76
RS
5741 /* Calculate the total size of temporary needed. */
5742 size = compute_overall_iter_number (nested_forall_info, inner_size,
5743 &inner_size_body, block);
5744
ae772c2d 5745 /* Check whether the size is negative. */
63ee5404 5746 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, size,
bc98ed60
TB
5747 gfc_index_zero_node);
5748 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
5749 cond, gfc_index_zero_node, size);
ae772c2d
PT
5750 size = gfc_evaluate_now (size, block);
5751
011daa76
RS
5752 /* Allocate temporary for WHERE mask if needed. */
5753 if (need_cmask)
5754 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5755 &pcmask);
5756
5757 /* Allocate temporary for !mask if needed. */
5758 if (need_pmask)
5759 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5760 &ppmask);
3891cee2
RS
5761 }
5762
6de9cd9a
DN
5763 while (cblock)
5764 {
011daa76
RS
5765 /* Each time around this loop, the where clause is conditional
5766 on the value of mask and invert, which are updated at the
5767 bottom of the loop. */
5768
6de9cd9a 5769 /* Has mask-expr. */
a513927a 5770 if (cblock->expr1)
6de9cd9a 5771 {
90f58ec8
RS
5772 /* Ensure that the WHERE mask will be evaluated exactly once.
5773 If there are no statements in this WHERE/ELSEWHERE clause,
5774 then we don't need to update the control mask (cmask).
5775 If this is the last clause of the WHERE construct, then
3891cee2 5776 we don't need to update the pending control mask (pmask). */
011daa76 5777 if (mask)
a513927a 5778 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
011daa76
RS
5779 mask, invert,
5780 cblock->next ? cmask : NULL_TREE,
5781 cblock->block ? pmask : NULL_TREE,
5782 mask_type, block);
5783 else
a513927a 5784 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
011daa76
RS
5785 NULL_TREE, false,
5786 (cblock->next || cblock->block)
5787 ? cmask : NULL_TREE,
5788 NULL_TREE, mask_type, block);
6de9cd9a 5789
011daa76 5790 invert = false;
6de9cd9a 5791 }
90f58ec8 5792 /* It's a final elsewhere-stmt. No mask-expr is present. */
6de9cd9a 5793 else
3891cee2 5794 cmask = mask;
6de9cd9a 5795
011daa76
RS
5796 /* The body of this where clause are controlled by cmask with
5797 sense specified by invert. */
5798
6de9cd9a
DN
5799 /* Get the assignment statement of a WHERE statement, or the first
5800 statement in where-body-construct of a WHERE construct. */
5801 cnext = cblock->next;
5802 while (cnext)
5803 {
5804 switch (cnext->op)
5805 {
5806 /* WHERE assignment statement. */
a00b8d1a
PT
5807 case EXEC_ASSIGN_CALL:
5808
5809 arg = cnext->ext.actual;
5810 expr1 = expr2 = NULL;
5811 for (; arg; arg = arg->next)
5812 {
5813 if (!arg->expr)
5814 continue;
5815 if (expr1 == NULL)
5816 expr1 = arg->expr;
5817 else
5818 expr2 = arg->expr;
5819 }
5820 goto evaluate;
5821
6de9cd9a 5822 case EXEC_ASSIGN:
a513927a 5823 expr1 = cnext->expr1;
6de9cd9a 5824 expr2 = cnext->expr2;
a00b8d1a 5825 evaluate:
6de9cd9a
DN
5826 if (nested_forall_info != NULL)
5827 {
3ded6210 5828 need_temp = gfc_check_dependency (expr1, expr2, 0);
7bd5dad2
LK
5829 if ((need_temp || flag_test_forall_temp)
5830 && cnext->op != EXEC_ASSIGN_CALL)
011daa76
RS
5831 gfc_trans_assign_need_temp (expr1, expr2,
5832 cmask, invert,
6de9cd9a
DN
5833 nested_forall_info, block);
5834 else
5835 {
5836 /* Variables to control maskexpr. */
5837 count1 = gfc_create_var (gfc_array_index_type, "count1");
5838 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
5839 gfc_add_modify (block, count1, gfc_index_zero_node);
5840 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 5841
011daa76
RS
5842 tmp = gfc_trans_where_assign (expr1, expr2,
5843 cmask, invert,
a00b8d1a 5844 count1, count2,
eb74e79b 5845 cnext);
8de1f441 5846
6de9cd9a 5847 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
bfcabc6c 5848 tmp, 1);
6de9cd9a
DN
5849 gfc_add_expr_to_block (block, tmp);
5850 }
5851 }
5852 else
5853 {
5854 /* Variables to control maskexpr. */
5855 count1 = gfc_create_var (gfc_array_index_type, "count1");
5856 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
5857 gfc_add_modify (block, count1, gfc_index_zero_node);
5858 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 5859
011daa76
RS
5860 tmp = gfc_trans_where_assign (expr1, expr2,
5861 cmask, invert,
a00b8d1a 5862 count1, count2,
eb74e79b 5863 cnext);
6de9cd9a
DN
5864 gfc_add_expr_to_block (block, tmp);
5865
5866 }
5867 break;
5868
5869 /* WHERE or WHERE construct is part of a where-body-construct. */
5870 case EXEC_WHERE:
011daa76
RS
5871 gfc_trans_where_2 (cnext, cmask, invert,
5872 nested_forall_info, block);
3891cee2 5873 break;
6de9cd9a
DN
5874
5875 default:
6e45f57b 5876 gcc_unreachable ();
6de9cd9a
DN
5877 }
5878
5879 /* The next statement within the same where-body-construct. */
5880 cnext = cnext->next;
5881 }
5882 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
5883 cblock = cblock->block;
011daa76
RS
5884 if (mask == NULL_TREE)
5885 {
5886 /* If we're the initial WHERE, we can simply invert the sense
5887 of the current mask to obtain the "mask" for the remaining
5888 ELSEWHEREs. */
5889 invert = true;
5890 mask = cmask;
5891 }
5892 else
5893 {
5894 /* Otherwise, for nested WHERE's we need to use the pending mask. */
5895 invert = false;
5896 mask = pmask;
5897 }
6de9cd9a 5898 }
3891cee2
RS
5899
5900 /* If we allocated a pending mask array, deallocate it now. */
5901 if (ppmask)
5902 {
1529b8d9 5903 tmp = gfc_call_free (ppmask);
3891cee2
RS
5904 gfc_add_expr_to_block (block, tmp);
5905 }
5906
5907 /* If we allocated a current mask array, deallocate it now. */
5908 if (pcmask)
5909 {
1529b8d9 5910 tmp = gfc_call_free (pcmask);
3891cee2
RS
5911 gfc_add_expr_to_block (block, tmp);
5912 }
6de9cd9a
DN
5913}
5914
3ded6210
RS
5915/* Translate a simple WHERE construct or statement without dependencies.
5916 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
5917 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
5918 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
5919
5920static tree
5921gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
5922{
5923 stmtblock_t block, body;
5924 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
5925 tree tmp, cexpr, tstmt, estmt;
5926 gfc_ss *css, *tdss, *tsss;
5927 gfc_se cse, tdse, tsse, edse, esse;
5928 gfc_loopinfo loop;
5929 gfc_ss *edss = 0;
5930 gfc_ss *esss = 0;
57bf3072 5931 bool maybe_workshare = false;
3ded6210 5932
34d01e1d 5933 /* Allow the scalarizer to workshare simple where loops. */
57bf3072
JJ
5934 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
5935 == OMPWS_WORKSHARE_FLAG)
5936 {
5937 maybe_workshare = true;
5938 ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
5939 }
34d01e1d 5940
a513927a
SK
5941 cond = cblock->expr1;
5942 tdst = cblock->next->expr1;
3ded6210 5943 tsrc = cblock->next->expr2;
a513927a 5944 edst = eblock ? eblock->next->expr1 : NULL;
3ded6210
RS
5945 esrc = eblock ? eblock->next->expr2 : NULL;
5946
5947 gfc_start_block (&block);
5948 gfc_init_loopinfo (&loop);
5949
5950 /* Handle the condition. */
5951 gfc_init_se (&cse, NULL);
5952 css = gfc_walk_expr (cond);
5953 gfc_add_ss_to_loop (&loop, css);
5954
5955 /* Handle the then-clause. */
5956 gfc_init_se (&tdse, NULL);
5957 gfc_init_se (&tsse, NULL);
5958 tdss = gfc_walk_expr (tdst);
5959 tsss = gfc_walk_expr (tsrc);
5960 if (tsss == gfc_ss_terminator)
5961 {
26f77530 5962 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
42d0058e 5963 tsss->info->where = 1;
3ded6210
RS
5964 }
5965 gfc_add_ss_to_loop (&loop, tdss);
5966 gfc_add_ss_to_loop (&loop, tsss);
5967
5968 if (eblock)
5969 {
5970 /* Handle the else clause. */
5971 gfc_init_se (&edse, NULL);
5972 gfc_init_se (&esse, NULL);
5973 edss = gfc_walk_expr (edst);
5974 esss = gfc_walk_expr (esrc);
5975 if (esss == gfc_ss_terminator)
5976 {
26f77530 5977 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
42d0058e 5978 esss->info->where = 1;
3ded6210
RS
5979 }
5980 gfc_add_ss_to_loop (&loop, edss);
5981 gfc_add_ss_to_loop (&loop, esss);
5982 }
5983
5984 gfc_conv_ss_startstride (&loop);
bdfd2ff0 5985 gfc_conv_loop_setup (&loop, &tdst->where);
3ded6210
RS
5986
5987 gfc_mark_ss_chain_used (css, 1);
5988 gfc_mark_ss_chain_used (tdss, 1);
5989 gfc_mark_ss_chain_used (tsss, 1);
5990 if (eblock)
5991 {
5992 gfc_mark_ss_chain_used (edss, 1);
5993 gfc_mark_ss_chain_used (esss, 1);
5994 }
5995
5996 gfc_start_scalarized_body (&loop, &body);
5997
5998 gfc_copy_loopinfo_to_se (&cse, &loop);
5999 gfc_copy_loopinfo_to_se (&tdse, &loop);
6000 gfc_copy_loopinfo_to_se (&tsse, &loop);
6001 cse.ss = css;
6002 tdse.ss = tdss;
6003 tsse.ss = tsss;
6004 if (eblock)
6005 {
6006 gfc_copy_loopinfo_to_se (&edse, &loop);
6007 gfc_copy_loopinfo_to_se (&esse, &loop);
6008 edse.ss = edss;
6009 esse.ss = esss;
6010 }
6011
6012 gfc_conv_expr (&cse, cond);
6013 gfc_add_block_to_block (&body, &cse.pre);
6014 cexpr = cse.expr;
6015
6016 gfc_conv_expr (&tsse, tsrc);
6017 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
3db5d687 6018 gfc_conv_tmp_array_ref (&tdse);
3ded6210
RS
6019 else
6020 gfc_conv_expr (&tdse, tdst);
6021
6022 if (eblock)
6023 {
6024 gfc_conv_expr (&esse, esrc);
6025 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
3db5d687 6026 gfc_conv_tmp_array_ref (&edse);
3ded6210 6027 else
3db5d687 6028 gfc_conv_expr (&edse, edst);
3ded6210
RS
6029 }
6030
ed673c00
MM
6031 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, true);
6032 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts,
2b56d6a4 6033 false, true)
c2255bc4 6034 : build_empty_stmt (input_location);
3ded6210
RS
6035 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
6036 gfc_add_expr_to_block (&body, tmp);
6037 gfc_add_block_to_block (&body, &cse.post);
6038
57bf3072
JJ
6039 if (maybe_workshare)
6040 ompws_flags &= ~OMPWS_SCALARIZER_BODY;
3ded6210
RS
6041 gfc_trans_scalarizing_loops (&loop, &body);
6042 gfc_add_block_to_block (&block, &loop.pre);
6043 gfc_add_block_to_block (&block, &loop.post);
6044 gfc_cleanup_loop (&loop);
6045
6046 return gfc_finish_block (&block);
6047}
6de9cd9a
DN
6048
6049/* As the WHERE or WHERE construct statement can be nested, we call
6050 gfc_trans_where_2 to do the translation, and pass the initial
f7b529fa 6051 NULL values for both the control mask and the pending control mask. */
6de9cd9a
DN
6052
6053tree
6054gfc_trans_where (gfc_code * code)
6055{
6056 stmtblock_t block;
3ded6210
RS
6057 gfc_code *cblock;
6058 gfc_code *eblock;
6de9cd9a 6059
3ded6210
RS
6060 cblock = code->block;
6061 if (cblock->next
6062 && cblock->next->op == EXEC_ASSIGN
6063 && !cblock->next->next)
6064 {
6065 eblock = cblock->block;
6066 if (!eblock)
6067 {
6068 /* A simple "WHERE (cond) x = y" statement or block is
6069 dependence free if cond is not dependent upon writing x,
6070 and the source y is unaffected by the destination x. */
a513927a
SK
6071 if (!gfc_check_dependency (cblock->next->expr1,
6072 cblock->expr1, 0)
6073 && !gfc_check_dependency (cblock->next->expr1,
3ded6210
RS
6074 cblock->next->expr2, 0))
6075 return gfc_trans_where_3 (cblock, NULL);
6076 }
a513927a 6077 else if (!eblock->expr1
3ded6210
RS
6078 && !eblock->block
6079 && eblock->next
6080 && eblock->next->op == EXEC_ASSIGN
6081 && !eblock->next->next)
6082 {
6083 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
6084 block is dependence free if cond is not dependent on writes
6085 to x1 and x2, y1 is not dependent on writes to x2, and y2
6086 is not dependent on writes to x1, and both y's are not
ae772c2d
PT
6087 dependent upon their own x's. In addition to this, the
6088 final two dependency checks below exclude all but the same
6089 array reference if the where and elswhere destinations
6090 are the same. In short, this is VERY conservative and this
6091 is needed because the two loops, required by the standard
6092 are coalesced in gfc_trans_where_3. */
524af0d6 6093 if (!gfc_check_dependency (cblock->next->expr1,
a513927a 6094 cblock->expr1, 0)
524af0d6 6095 && !gfc_check_dependency (eblock->next->expr1,
a513927a 6096 cblock->expr1, 0)
524af0d6 6097 && !gfc_check_dependency (cblock->next->expr1,
ae772c2d 6098 eblock->next->expr2, 1)
524af0d6 6099 && !gfc_check_dependency (eblock->next->expr1,
ae772c2d 6100 cblock->next->expr2, 1)
524af0d6 6101 && !gfc_check_dependency (cblock->next->expr1,
ae772c2d 6102 cblock->next->expr2, 1)
524af0d6 6103 && !gfc_check_dependency (eblock->next->expr1,
ae772c2d 6104 eblock->next->expr2, 1)
524af0d6 6105 && !gfc_check_dependency (cblock->next->expr1,
a513927a 6106 eblock->next->expr1, 0)
524af0d6 6107 && !gfc_check_dependency (eblock->next->expr1,
a513927a 6108 cblock->next->expr1, 0))
3ded6210
RS
6109 return gfc_trans_where_3 (cblock, eblock);
6110 }
6111 }
6112
6de9cd9a 6113 gfc_start_block (&block);
6de9cd9a 6114
011daa76 6115 gfc_trans_where_2 (code, NULL, false, NULL, &block);
6de9cd9a 6116
6de9cd9a
DN
6117 return gfc_finish_block (&block);
6118}
6119
6120
6121/* CYCLE a DO loop. The label decl has already been created by
6122 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
6123 node at the head of the loop. We must mark the label as used. */
6124
6125tree
6126gfc_trans_cycle (gfc_code * code)
6127{
6128 tree cycle_label;
6129
e5ca9693
DK
6130 cycle_label = code->ext.which_construct->cycle_label;
6131 gcc_assert (cycle_label);
6132
6de9cd9a
DN
6133 TREE_USED (cycle_label) = 1;
6134 return build1_v (GOTO_EXPR, cycle_label);
6135}
6136
6137
e7dc5b4f 6138/* EXIT a DO loop. Similar to CYCLE, but now the label is in
6de9cd9a
DN
6139 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
6140 loop. */
6141
6142tree
6143gfc_trans_exit (gfc_code * code)
6144{
6145 tree exit_label;
6146
e5ca9693
DK
6147 exit_label = code->ext.which_construct->exit_label;
6148 gcc_assert (exit_label);
6149
6de9cd9a
DN
6150 TREE_USED (exit_label) = 1;
6151 return build1_v (GOTO_EXPR, exit_label);
6152}
6153
6154
cc03bf7a
AV
6155/* Get the initializer expression for the code and expr of an allocate.
6156 When no initializer is needed return NULL. */
6157
6158static gfc_expr *
6159allocate_get_initializer (gfc_code * code, gfc_expr * expr)
6160{
6161 if (!gfc_bt_struct (expr->ts.type) && expr->ts.type != BT_CLASS)
6162 return NULL;
6163
6164 /* An explicit type was given in allocate ( T:: object). */
6165 if (code->ext.alloc.ts.type == BT_DERIVED
6166 && (code->ext.alloc.ts.u.derived->attr.alloc_comp
6167 || gfc_has_default_initializer (code->ext.alloc.ts.u.derived)))
6168 return gfc_default_initializer (&code->ext.alloc.ts);
6169
6170 if (gfc_bt_struct (expr->ts.type)
6171 && (expr->ts.u.derived->attr.alloc_comp
6172 || gfc_has_default_initializer (expr->ts.u.derived)))
6173 return gfc_default_initializer (&expr->ts);
6174
6175 if (expr->ts.type == BT_CLASS
6176 && (CLASS_DATA (expr)->ts.u.derived->attr.alloc_comp
6177 || gfc_has_default_initializer (CLASS_DATA (expr)->ts.u.derived)))
6178 return gfc_default_initializer (&CLASS_DATA (expr)->ts);
6179
6180 return NULL;
6181}
6182
6de9cd9a
DN
6183/* Translate the ALLOCATE statement. */
6184
6185tree
6186gfc_trans_allocate (gfc_code * code)
6187{
6188 gfc_alloc *al;
cc03bf7a 6189 gfc_expr *expr, *e3rhs = NULL, *init_expr;
34d9d749 6190 gfc_se se, se_sz;
6de9cd9a
DN
6191 tree tmp;
6192 tree parm;
6de9cd9a 6193 tree stat;
8f992d64
DC
6194 tree errmsg;
6195 tree errlen;
6196 tree label_errmsg;
6197 tree label_finish;
60f5ed26 6198 tree memsz;
34d9d749
AV
6199 tree al_vptr, al_len;
6200 /* If an expr3 is present, then store the tree for accessing its
6201 _vptr, and _len components in the variables, respectively. The
6202 element size, i.e. _vptr%size, is stored in expr3_esize. Any of
6203 the trees may be the NULL_TREE indicating that this is not
6204 available for expr3's type. */
6205 tree expr3, expr3_vptr, expr3_len, expr3_esize;
1792349b
AV
6206 /* Classify what expr3 stores. */
6207 enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
6de9cd9a 6208 stmtblock_t block;
90cf3ecc 6209 stmtblock_t post;
1312bb90 6210 stmtblock_t final_block;
4daa71b0 6211 tree nelems;
525a5e33
AV
6212 bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set, is_coarray;
6213 bool needs_caf_sync, caf_refs_comp;
c1525930 6214 bool e3_has_nodescriptor = false;
db7ffcab 6215 gfc_symtree *newsym = NULL;
525a5e33 6216 symbol_attribute caf_attr;
5bab4c96 6217 gfc_actual_arglist *param_list;
6de9cd9a 6218
cf2b3c22 6219 if (!code->ext.alloc.list)
6de9cd9a
DN
6220 return NULL_TREE;
6221
34d9d749
AV
6222 stat = tmp = memsz = al_vptr = al_len = NULL_TREE;
6223 expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE;
8f992d64 6224 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
1792349b 6225 e3_is = E3_UNSET;
525a5e33 6226 is_coarray = needs_caf_sync = false;
3759634f 6227
90cf3ecc
PT
6228 gfc_init_block (&block);
6229 gfc_init_block (&post);
1312bb90 6230 gfc_init_block (&final_block);
6de9cd9a 6231
8f992d64
DC
6232 /* STAT= (and maybe ERRMSG=) is present. */
6233 if (code->expr1)
6de9cd9a 6234 {
8f992d64 6235 /* STAT=. */
e2cad04b 6236 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 6237 stat = gfc_create_var (gfc_int4_type_node, "stat");
6de9cd9a 6238
8f992d64
DC
6239 /* ERRMSG= only makes sense with STAT=. */
6240 if (code->expr2)
6241 {
6242 gfc_init_se (&se, NULL);
5d81ddd0 6243 se.want_pointer = 1;
8f992d64 6244 gfc_conv_expr_lhs (&se, code->expr2);
5d81ddd0
TB
6245 errmsg = se.expr;
6246 errlen = se.string_length;
8f992d64
DC
6247 }
6248 else
6249 {
6250 errmsg = null_pointer_node;
6251 errlen = build_int_cst (gfc_charlen_type_node, 0);
6252 }
6253
6254 /* GOTO destinations. */
6255 label_errmsg = gfc_build_label_decl (NULL_TREE);
6256 label_finish = gfc_build_label_decl (NULL_TREE);
5d81ddd0 6257 TREE_USED (label_finish) = 0;
6de9cd9a 6258 }
6de9cd9a 6259
db7ffcab
AV
6260 /* When an expr3 is present evaluate it only once. The standards prevent a
6261 dependency of expr3 on the objects in the allocate list. An expr3 can
6262 be pre-evaluated in all cases. One just has to make sure, to use the
6263 correct way, i.e., to get the descriptor or to get a reference
6264 expression. */
34d9d749
AV
6265 if (code->expr3)
6266 {
139d4065
AV
6267 bool vtab_needed = false, temp_var_needed = false,
6268 temp_obj_created = false;
ffaf9305
AV
6269
6270 is_coarray = gfc_is_coarray (code->expr3);
34d9d749 6271
1312bb90
PT
6272 if (code->expr3->expr_type == EXPR_FUNCTION && !code->expr3->mold
6273 && (gfc_is_class_array_function (code->expr3)
6274 || gfc_is_alloc_class_scalar_function (code->expr3)))
6275 code->expr3->must_finalize = 1;
6276
34d9d749
AV
6277 /* Figure whether we need the vtab from expr3. */
6278 for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
6279 al = al->next)
6280 vtab_needed = (al->expr->ts.type == BT_CLASS);
6281
1792349b 6282 gfc_init_se (&se, NULL);
db7ffcab 6283 /* When expr3 is a variable, i.e., a very simple expression,
34d9d749 6284 then convert it once here. */
db7ffcab
AV
6285 if (code->expr3->expr_type == EXPR_VARIABLE
6286 || code->expr3->expr_type == EXPR_ARRAY
6287 || code->expr3->expr_type == EXPR_CONSTANT)
6288 {
6289 if (!code->expr3->mold
6290 || code->expr3->ts.type == BT_CHARACTER
1792349b
AV
6291 || vtab_needed
6292 || code->ext.alloc.arr_spec_from_expr3)
34d9d749 6293 {
1792349b
AV
6294 /* Convert expr3 to a tree. For all "simple" expression just
6295 get the descriptor or the reference, respectively, depending
6296 on the rank of the expr. */
6297 if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
440f9408
AV
6298 gfc_conv_expr_descriptor (&se, code->expr3);
6299 else
1c645536
AV
6300 {
6301 gfc_conv_expr_reference (&se, code->expr3);
6302
6303 /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a
6304 NOP_EXPR, which prevents gfortran from getting the vptr
6305 from the source=-expression. Remove the NOP_EXPR and go
6306 with the POINTER_PLUS_EXPR in this case. */
6307 if (code->expr3->ts.type == BT_CLASS
6308 && TREE_CODE (se.expr) == NOP_EXPR
781d83d9
AV
6309 && (TREE_CODE (TREE_OPERAND (se.expr, 0))
6310 == POINTER_PLUS_EXPR
6311 || is_coarray))
1c645536
AV
6312 se.expr = TREE_OPERAND (se.expr, 0);
6313 }
1792349b
AV
6314 /* Create a temp variable only for component refs to prevent
6315 having to go through the full deref-chain each time and to
6316 simplfy computation of array properties. */
6317 temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF;
db7ffcab 6318 }
db7ffcab
AV
6319 }
6320 else
6321 {
1792349b 6322 /* In all other cases evaluate the expr3. */
db7ffcab
AV
6323 symbol_attribute attr;
6324 /* Get the descriptor for all arrays, that are not allocatable or
b8ac4f3b
AV
6325 pointer, because the latter are descriptors already.
6326 The exception are function calls returning a class object:
6327 The descriptor is stored in their results _data component, which
6328 is easier to access, when first a temporary variable for the
6329 result is created and the descriptor retrieved from there. */
db7ffcab 6330 attr = gfc_expr_attr (code->expr3);
b8ac4f3b
AV
6331 if (code->expr3->rank != 0
6332 && ((!attr.allocatable && !attr.pointer)
6333 || (code->expr3->expr_type == EXPR_FUNCTION
574284e9
AV
6334 && (code->expr3->ts.type != BT_CLASS
6335 || (code->expr3->value.function.isym
6336 && code->expr3->value.function.isym
6337 ->transformational)))))
db7ffcab
AV
6338 gfc_conv_expr_descriptor (&se, code->expr3);
6339 else
6340 gfc_conv_expr_reference (&se, code->expr3);
6341 if (code->expr3->ts.type == BT_CLASS)
6342 gfc_conv_class_to_class (&se, code->expr3,
6343 code->expr3->ts,
6344 false, true,
6345 false, false);
139d4065 6346 temp_obj_created = temp_var_needed = !VAR_P (se.expr);
1792349b
AV
6347 }
6348 gfc_add_block_to_block (&block, &se.pre);
1312bb90
PT
6349 if (code->expr3->must_finalize)
6350 gfc_add_block_to_block (&final_block, &se.post);
6351 else
6352 gfc_add_block_to_block (&post, &se.post);
64e56ab0
AV
6353
6354 /* Special case when string in expr3 is zero. */
6355 if (code->expr3->ts.type == BT_CHARACTER
6356 && integer_zerop (se.string_length))
6357 {
6358 gfc_init_se (&se, NULL);
6359 temp_var_needed = false;
f622221a 6360 expr3_len = build_zero_cst (gfc_charlen_type_node);
64e56ab0
AV
6361 e3_is = E3_MOLD;
6362 }
1792349b
AV
6363 /* Prevent aliasing, i.e., se.expr may be already a
6364 variable declaration. */
64e56ab0 6365 else if (se.expr != NULL_TREE && temp_var_needed)
1792349b 6366 {
b8ac4f3b 6367 tree var, desc;
781d83d9 6368 tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
1792349b
AV
6369 se.expr
6370 : build_fold_indirect_ref_loc (input_location, se.expr);
b8ac4f3b
AV
6371
6372 /* Get the array descriptor and prepare it to be assigned to the
6373 temporary variable var. For classes the array descriptor is
6374 in the _data component and the object goes into the
6375 GFC_DECL_SAVED_DESCRIPTOR. */
6376 if (code->expr3->ts.type == BT_CLASS
6377 && code->expr3->rank != 0)
6378 {
6379 /* When an array_ref was in expr3, then the descriptor is the
6380 first operand. */
781d83d9 6381 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
b8ac4f3b
AV
6382 {
6383 desc = TREE_OPERAND (tmp, 0);
6384 }
6385 else
6386 {
6387 desc = tmp;
6388 tmp = gfc_class_data_get (tmp);
6389 }
92c5266b
AV
6390 if (code->ext.alloc.arr_spec_from_expr3)
6391 e3_is = E3_DESC;
b8ac4f3b
AV
6392 }
6393 else
781d83d9
AV
6394 desc = !is_coarray ? se.expr
6395 : TREE_OPERAND (TREE_OPERAND (se.expr, 0), 0);
1792349b
AV
6396 /* We need a regular (non-UID) symbol here, therefore give a
6397 prefix. */
6398 var = gfc_create_var (TREE_TYPE (tmp), "source");
781d83d9 6399 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
db7ffcab 6400 {
1792349b 6401 gfc_allocate_lang_decl (var);
b8ac4f3b 6402 GFC_DECL_SAVED_DESCRIPTOR (var) = desc;
1792349b
AV
6403 }
6404 gfc_add_modify_loc (input_location, &block, var, tmp);
26e46e4b 6405
1792349b 6406 expr3 = var;
db7ffcab 6407 if (se.string_length)
1792349b 6408 /* Evaluate it assuming that it also is complicated like expr3. */
db7ffcab 6409 expr3_len = gfc_evaluate_now (se.string_length, &block);
34d9d749 6410 }
1792349b
AV
6411 else
6412 {
6413 expr3 = se.expr;
6414 expr3_len = se.string_length;
6415 }
3cae214f
PT
6416
6417 /* Deallocate any allocatable components in expressions that use a
139d4065
AV
6418 temporary object, i.e. are not a simple alias of to an EXPR_VARIABLE.
6419 E.g. temporaries of a function call need freeing of their components
6420 here. */
3cae214f
PT
6421 if ((code->expr3->ts.type == BT_DERIVED
6422 || code->expr3->ts.type == BT_CLASS)
139d4065 6423 && (code->expr3->expr_type != EXPR_VARIABLE || temp_obj_created)
fd876246
PT
6424 && code->expr3->ts.u.derived->attr.alloc_comp
6425 && !code->expr3->must_finalize)
3cae214f
PT
6426 {
6427 tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
6428 expr3, code->expr3->rank);
6429 gfc_prepend_expr_to_block (&post, tmp);
6430 }
6431
1792349b 6432 /* Store what the expr3 is to be used for. */
b8ac4f3b
AV
6433 if (e3_is == E3_UNSET)
6434 e3_is = expr3 != NULL_TREE ?
6435 (code->ext.alloc.arr_spec_from_expr3 ?
6436 E3_DESC
6437 : (code->expr3->mold ? E3_MOLD : E3_SOURCE))
6438 : E3_UNSET;
34d9d749
AV
6439
6440 /* Figure how to get the _vtab entry. This also obtains the tree
6441 expression for accessing the _len component, because only
6442 unlimited polymorphic objects, which are a subcategory of class
6443 types, have a _len component. */
6444 if (code->expr3->ts.type == BT_CLASS)
6445 {
6446 gfc_expr *rhs;
b8ac4f3b
AV
6447 tmp = expr3 != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (expr3)) ?
6448 build_fold_indirect_ref (expr3): expr3;
db7ffcab
AV
6449 /* Polymorphic SOURCE: VPTR must be determined at run time.
6450 expr3 may be a temporary array declaration, therefore check for
6451 GFC_CLASS_TYPE_P before trying to get the _vptr component. */
b8ac4f3b 6452 if (tmp != NULL_TREE
b8ac4f3b
AV
6453 && (e3_is == E3_DESC
6454 || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
6455 && (VAR_P (tmp) || !code->expr3->ref))
6456 || (VAR_P (tmp) && DECL_LANG_SPECIFIC (tmp))))
34d9d749 6457 tmp = gfc_class_vptr_get (expr3);
34d9d749
AV
6458 else
6459 {
6460 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
6461 gfc_add_vptr_component (rhs);
6462 gfc_init_se (&se, NULL);
6463 se.want_pointer = 1;
6464 gfc_conv_expr (&se, rhs);
6465 tmp = se.expr;
6466 gfc_free_expr (rhs);
6467 }
6468 /* Set the element size. */
6469 expr3_esize = gfc_vptr_size_get (tmp);
6470 if (vtab_needed)
6471 expr3_vptr = tmp;
6472 /* Initialize the ref to the _len component. */
6473 if (expr3_len == NULL_TREE && UNLIMITED_POLY (code->expr3))
6474 {
6475 /* Same like for retrieving the _vptr. */
6476 if (expr3 != NULL_TREE && !code->expr3->ref)
1792349b 6477 expr3_len = gfc_class_len_get (expr3);
34d9d749
AV
6478 else
6479 {
6480 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
6481 gfc_add_len_component (rhs);
6482 gfc_init_se (&se, NULL);
6483 gfc_conv_expr (&se, rhs);
6484 expr3_len = se.expr;
6485 gfc_free_expr (rhs);
6486 }
6487 }
6488 }
6489 else
6490 {
6491 /* When the object to allocate is polymorphic type, then it
6492 needs its vtab set correctly, so deduce the required _vtab
6493 and _len from the source expression. */
6494 if (vtab_needed)
6495 {
6496 /* VPTR is fixed at compile time. */
6497 gfc_symbol *vtab;
90cf3ecc 6498
34d9d749
AV
6499 vtab = gfc_find_vtab (&code->expr3->ts);
6500 gcc_assert (vtab);
6501 expr3_vptr = gfc_get_symbol_decl (vtab);
6502 expr3_vptr = gfc_build_addr_expr (NULL_TREE,
6503 expr3_vptr);
6504 }
6505 /* _len component needs to be set, when ts is a character
6506 array. */
6507 if (expr3_len == NULL_TREE
6508 && code->expr3->ts.type == BT_CHARACTER)
6509 {
6510 if (code->expr3->ts.u.cl
6511 && code->expr3->ts.u.cl->length)
6512 {
6513 gfc_init_se (&se, NULL);
6514 gfc_conv_expr (&se, code->expr3->ts.u.cl->length);
6515 gfc_add_block_to_block (&block, &se.pre);
6516 expr3_len = gfc_evaluate_now (se.expr, &block);
6517 }
6518 gcc_assert (expr3_len);
6519 }
6520 /* For character arrays only the kind's size is needed, because
6521 the array mem_size is _len * (elem_size = kind_size).
6522 For all other get the element size in the normal way. */
6523 if (code->expr3->ts.type == BT_CHARACTER)
6524 expr3_esize = TYPE_SIZE_UNIT (
6525 gfc_get_char_type (code->expr3->ts.kind));
6526 else
6527 expr3_esize = TYPE_SIZE_UNIT (
6528 gfc_typenode_for_spec (&code->expr3->ts));
6529 }
6530 gcc_assert (expr3_esize);
6531 expr3_esize = fold_convert (sizetype, expr3_esize);
1792349b 6532 if (e3_is == E3_MOLD)
64e56ab0
AV
6533 /* The expr3 is no longer valid after this point. */
6534 expr3 = NULL_TREE;
34d9d749
AV
6535 }
6536 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
6537 {
6538 /* Compute the explicit typespec given only once for all objects
6539 to allocate. */
6540 if (code->ext.alloc.ts.type != BT_CHARACTER)
6541 expr3_esize = TYPE_SIZE_UNIT (
6542 gfc_typenode_for_spec (&code->ext.alloc.ts));
8cd119d8 6543 else if (code->ext.alloc.ts.u.cl->length != NULL)
34d9d749
AV
6544 {
6545 gfc_expr *sz;
34d9d749
AV
6546 sz = gfc_copy_expr (code->ext.alloc.ts.u.cl->length);
6547 gfc_init_se (&se_sz, NULL);
6548 gfc_conv_expr (&se_sz, sz);
6549 gfc_free_expr (sz);
6550 tmp = gfc_get_char_type (code->ext.alloc.ts.kind);
6551 tmp = TYPE_SIZE_UNIT (tmp);
6552 tmp = fold_convert (TREE_TYPE (se_sz.expr), tmp);
69aaea06 6553 gfc_add_block_to_block (&block, &se_sz.pre);
34d9d749
AV
6554 expr3_esize = fold_build2_loc (input_location, MULT_EXPR,
6555 TREE_TYPE (se_sz.expr),
6556 tmp, se_sz.expr);
69aaea06 6557 expr3_esize = gfc_evaluate_now (expr3_esize, &block);
34d9d749 6558 }
8cd119d8
PT
6559 else
6560 expr3_esize = NULL_TREE;
34d9d749
AV
6561 }
6562
574284e9
AV
6563 /* The routine gfc_trans_assignment () already implements all
6564 techniques needed. Unfortunately we may have a temporary
6565 variable for the source= expression here. When that is the
6566 case convert this variable into a temporary gfc_expr of type
6567 EXPR_VARIABLE and used it as rhs for the assignment. The
6568 advantage is, that we get scalarizer support for free,
6569 don't have to take care about scalar to array treatment and
6570 will benefit of every enhancements gfc_trans_assignment ()
6571 gets.
6572 No need to check whether e3_is is E3_UNSET, because that is
6573 done by expr3 != NULL_TREE.
6574 Exclude variables since the following block does not handle
6575 array sections. In any case, there is no harm in sending
6576 variables to gfc_trans_assignment because there is no
6577 evaluation of variables. */
6578 if (code->expr3)
6579 {
6580 if (code->expr3->expr_type != EXPR_VARIABLE
6581 && e3_is != E3_MOLD && expr3 != NULL_TREE
6582 && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
6583 {
6584 /* Build a temporary symtree and symbol. Do not add it to the current
6585 namespace to prevent accidently modifying a colliding
6586 symbol's as. */
6587 newsym = XCNEW (gfc_symtree);
6588 /* The name of the symtree should be unique, because gfc_create_var ()
6589 took care about generating the identifier. */
51f03c6b
JJ
6590 newsym->name
6591 = gfc_get_string ("%s", IDENTIFIER_POINTER (DECL_NAME (expr3)));
574284e9
AV
6592 newsym->n.sym = gfc_new_symbol (newsym->name, NULL);
6593 /* The backend_decl is known. It is expr3, which is inserted
6594 here. */
6595 newsym->n.sym->backend_decl = expr3;
6596 e3rhs = gfc_get_expr ();
6597 e3rhs->rank = code->expr3->rank;
6598 e3rhs->symtree = newsym;
6599 /* Mark the symbol referenced or gfc_trans_assignment will bug. */
6600 newsym->n.sym->attr.referenced = 1;
6601 e3rhs->expr_type = EXPR_VARIABLE;
6602 e3rhs->where = code->expr3->where;
6603 /* Set the symbols type, upto it was BT_UNKNOWN. */
6604 if (IS_CLASS_ARRAY (code->expr3)
6605 && code->expr3->expr_type == EXPR_FUNCTION
6606 && code->expr3->value.function.isym
6607 && code->expr3->value.function.isym->transformational)
6608 {
6609 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6610 }
6611 else if (code->expr3->ts.type == BT_CLASS
6612 && !GFC_CLASS_TYPE_P (TREE_TYPE (expr3)))
6613 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6614 else
6615 e3rhs->ts = code->expr3->ts;
6616 newsym->n.sym->ts = e3rhs->ts;
6617 /* Check whether the expr3 is array valued. */
6618 if (e3rhs->rank)
6619 {
6620 gfc_array_spec *arr;
6621 arr = gfc_get_array_spec ();
6622 arr->rank = e3rhs->rank;
6623 arr->type = AS_DEFERRED;
6624 /* Set the dimension and pointer attribute for arrays
6625 to be on the safe side. */
6626 newsym->n.sym->attr.dimension = 1;
6627 newsym->n.sym->attr.pointer = 1;
6628 newsym->n.sym->as = arr;
6629 if (IS_CLASS_ARRAY (code->expr3)
6630 && code->expr3->expr_type == EXPR_FUNCTION
6631 && code->expr3->value.function.isym
6632 && code->expr3->value.function.isym->transformational)
6633 {
6634 gfc_array_spec *tarr;
6635 tarr = gfc_get_array_spec ();
6636 *tarr = *arr;
6637 e3rhs->ts.u.derived->as = tarr;
6638 }
6639 gfc_add_full_array_ref (e3rhs, arr);
6640 }
6641 else if (POINTER_TYPE_P (TREE_TYPE (expr3)))
6642 newsym->n.sym->attr.pointer = 1;
6643 /* The string length is known, too. Set it for char arrays. */
6644 if (e3rhs->ts.type == BT_CHARACTER)
6645 newsym->n.sym->ts.u.cl->backend_decl = expr3_len;
6646 gfc_commit_symbol (newsym->n.sym);
6647 }
6648 else
6649 e3rhs = gfc_copy_expr (code->expr3);
c1525930 6650
6262e3a2
CLT
6651 // We need to propagate the bounds of the expr3 for source=/mold=.
6652 // However, for non-named arrays, the lbound has to be 1 and neither the
6653 // bound used inside the called function even when returning an
6654 // allocatable/pointer nor the zero used internally.
6655 if (e3_is == E3_DESC
6656 && code->expr3->expr_type != EXPR_VARIABLE)
6657 e3_has_nodescriptor = true;
574284e9
AV
6658 }
6659
34d9d749 6660 /* Loop over all objects to allocate. */
cf2b3c22 6661 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6de9cd9a 6662 {
f43085aa 6663 expr = gfc_copy_expr (al->expr);
34d9d749
AV
6664 /* UNLIMITED_POLY () needs the _data component to be set, when
6665 expr is a unlimited polymorphic object. But the _data component
6666 has not been set yet, so check the derived type's attr for the
6667 unlimited polymorphic flag to be safe. */
6668 upoly_expr = UNLIMITED_POLY (expr)
6669 || (expr->ts.type == BT_DERIVED
6670 && expr->ts.u.derived->attr.unlimited_polymorphic);
6671 gfc_init_se (&se, NULL);
f43085aa 6672
34d9d749
AV
6673 /* For class types prepare the expressions to ref the _vptr
6674 and the _len component. The latter for unlimited polymorphic
6675 types only. */
f43085aa 6676 if (expr->ts.type == BT_CLASS)
34d9d749
AV
6677 {
6678 gfc_expr *expr_ref_vptr, *expr_ref_len;
6679 gfc_add_data_component (expr);
6680 /* Prep the vptr handle. */
6681 expr_ref_vptr = gfc_copy_expr (al->expr);
6682 gfc_add_vptr_component (expr_ref_vptr);
6683 se.want_pointer = 1;
6684 gfc_conv_expr (&se, expr_ref_vptr);
6685 al_vptr = se.expr;
6686 se.want_pointer = 0;
6687 gfc_free_expr (expr_ref_vptr);
6688 /* Allocated unlimited polymorphic objects always have a _len
6689 component. */
6690 if (upoly_expr)
6691 {
6692 expr_ref_len = gfc_copy_expr (al->expr);
6693 gfc_add_len_component (expr_ref_len);
6694 gfc_conv_expr (&se, expr_ref_len);
6695 al_len = se.expr;
6696 gfc_free_expr (expr_ref_len);
6697 }
6698 else
6699 /* In a loop ensure that all loop variable dependent variables
6700 are initialized at the same spot in all execution paths. */
6701 al_len = NULL_TREE;
6702 }
6703 else
6704 al_vptr = al_len = NULL_TREE;
6de9cd9a
DN
6705
6706 se.want_pointer = 1;
6707 se.descriptor_only = 1;
78ab5260 6708
6de9cd9a 6709 gfc_conv_expr (&se, expr);
34d9d749
AV
6710 if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6711 /* se.string_length now stores the .string_length variable of expr
6712 needed to allocate character(len=:) arrays. */
6713 al_len = se.string_length;
6714
6715 al_len_needs_set = al_len != NULL_TREE;
67914693 6716 /* When allocating an array one cannot use much of the
34d9d749
AV
6717 pre-evaluated expr3 expressions, because for most of them the
6718 scalarizer is needed which is not available in the pre-evaluation
6719 step. Therefore gfc_array_allocate () is responsible (and able)
6720 to handle the complete array allocation. Only the element size
6721 needs to be provided, which is done most of the time by the
6722 pre-evaluation step. */
4daa71b0 6723 nelems = NULL_TREE;
764d5c7b
AV
6724 if (expr3_len && (code->expr3->ts.type == BT_CHARACTER
6725 || code->expr3->ts.type == BT_CLASS))
6726 {
6727 /* When al is an array, then the element size for each element
6728 in the array is needed, which is the product of the len and
6729 esize for char arrays. For unlimited polymorphics len can be
6730 zero, therefore take the maximum of len and one. */
6731 tmp = fold_build2_loc (input_location, MAX_EXPR,
6732 TREE_TYPE (expr3_len),
6733 expr3_len, fold_convert (TREE_TYPE (expr3_len),
6734 integer_one_node));
6735 tmp = fold_build2_loc (input_location, MULT_EXPR,
6736 TREE_TYPE (expr3_esize), expr3_esize,
6737 fold_convert (TREE_TYPE (expr3_esize), tmp));
6738 }
34d9d749
AV
6739 else
6740 tmp = expr3_esize;
c1525930 6741
34d9d749 6742 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen,
1792349b
AV
6743 label_finish, tmp, &nelems,
6744 e3rhs ? e3rhs : code->expr3,
6745 e3_is == E3_DESC ? expr3 : NULL_TREE,
c1525930 6746 e3_has_nodescriptor))
6de9cd9a 6747 {
34d9d749
AV
6748 /* A scalar or derived type. First compute the size to
6749 allocate.
cf2b3c22 6750
34d9d749
AV
6751 expr3_len is set when expr3 is an unlimited polymorphic
6752 object or a deferred length string. */
6753 if (expr3_len != NULL_TREE)
8d51f26f 6754 {
34d9d749
AV
6755 tmp = fold_convert (TREE_TYPE (expr3_esize), expr3_len);
6756 tmp = fold_build2_loc (input_location, MULT_EXPR,
6757 TREE_TYPE (expr3_esize),
6758 expr3_esize, tmp);
6759 if (code->expr3->ts.type != BT_CLASS)
6760 /* expr3 is a deferred length string, i.e., we are
6761 done. */
6762 memsz = tmp;
8d51f26f 6763 else
5b384b3d 6764 {
34d9d749
AV
6765 /* For unlimited polymorphic enties build
6766 (len > 0) ? element_size * len : element_size
6767 to compute the number of bytes to allocate.
6768 This allows the allocation of unlimited polymorphic
6769 objects from an expr3 that is also unlimited
6770 polymorphic and stores a _len dependent object,
6771 e.g., a string. */
6772 memsz = fold_build2_loc (input_location, GT_EXPR,
63ee5404 6773 logical_type_node, expr3_len,
f622221a
JB
6774 build_zero_cst
6775 (TREE_TYPE (expr3_len)));
34d9d749
AV
6776 memsz = fold_build3_loc (input_location, COND_EXPR,
6777 TREE_TYPE (expr3_esize),
6778 memsz, tmp, expr3_esize);
5b384b3d 6779 }
8d51f26f 6780 }
34d9d749
AV
6781 else if (expr3_esize != NULL_TREE)
6782 /* Any other object in expr3 just needs element size in
6783 bytes. */
6784 memsz = expr3_esize;
6785 else if ((expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6786 || (upoly_expr
6787 && code->ext.alloc.ts.type == BT_CHARACTER))
2573aab9 6788 {
34d9d749
AV
6789 /* Allocating deferred length char arrays need the length
6790 to allocate in the alloc_type_spec. But also unlimited
6791 polymorphic objects may be allocated as char arrays.
6792 Both are handled here. */
2573aab9
TB
6793 gfc_init_se (&se_sz, NULL);
6794 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6795 gfc_add_block_to_block (&se.pre, &se_sz.pre);
6796 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
6797 gfc_add_block_to_block (&se.pre, &se_sz.post);
34d9d749
AV
6798 expr3_len = se_sz.expr;
6799 tmp_expr3_len_flag = true;
6800 tmp = TYPE_SIZE_UNIT (
6801 gfc_get_char_type (code->ext.alloc.ts.kind));
2573aab9 6802 memsz = fold_build2_loc (input_location, MULT_EXPR,
34d9d749
AV
6803 TREE_TYPE (tmp),
6804 fold_convert (TREE_TYPE (tmp),
6805 expr3_len),
6806 tmp);
2573aab9 6807 }
34d9d749 6808 else if (expr->ts.type == BT_CHARACTER)
8d51f26f 6809 {
34d9d749
AV
6810 /* Compute the number of bytes needed to allocate a fixed
6811 length char array. */
6812 gcc_assert (se.string_length != NULL_TREE);
6813 tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind));
8d51f26f
PT
6814 memsz = fold_build2_loc (input_location, MULT_EXPR,
6815 TREE_TYPE (tmp), tmp,
34d9d749
AV
6816 fold_convert (TREE_TYPE (tmp),
6817 se.string_length));
8d51f26f 6818 }
34d9d749
AV
6819 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
6820 /* Handle all types, where the alloc_type_spec is set. */
6821 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
6822 else
6823 /* Handle size computation of the type declared to alloc. */
6f3d1a5e 6824 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
90cf3ecc 6825
525a5e33
AV
6826 /* Store the caf-attributes for latter use. */
6827 if (flag_coarray == GFC_FCOARRAY_LIB
6828 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
6829 .codimension)
3c9f5092
AV
6830 {
6831 /* Scalar allocatable components in coarray'ed derived types make
6832 it here and are treated now. */
6833 tree caf_decl, token;
6834 gfc_se caf_se;
6835
ffaf9305 6836 is_coarray = true;
525a5e33
AV
6837 /* Set flag, to add synchronize after the allocate. */
6838 needs_caf_sync = needs_caf_sync
6839 || caf_attr.coarray_comp || !caf_refs_comp;
ffaf9305 6840
3c9f5092
AV
6841 gfc_init_se (&caf_se, NULL);
6842
6843 caf_decl = gfc_get_tree_for_caf_expr (expr);
6844 gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl,
6845 NULL_TREE, NULL);
6846 gfc_add_block_to_block (&se.pre, &caf_se.pre);
6847 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
6848 gfc_build_addr_expr (NULL_TREE, token),
6849 NULL_TREE, NULL_TREE, NULL_TREE,
6850 label_finish, expr, 1);
6851 }
5b130807 6852 /* Allocate - for non-pointers with re-alloc checking. */
3c9f5092
AV
6853 else if (gfc_expr_attr (expr).allocatable)
6854 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
6855 NULL_TREE, stat, errmsg, errlen,
6856 label_finish, expr, 0);
90cf3ecc 6857 else
4f13e17f 6858 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
6de9cd9a 6859 }
34d9d749
AV
6860 else
6861 {
ffaf9305
AV
6862 /* Allocating coarrays needs a sync after the allocate executed.
6863 Set the flag to add the sync after all objects are allocated. */
525a5e33
AV
6864 if (flag_coarray == GFC_FCOARRAY_LIB
6865 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
6866 .codimension)
6867 {
6868 is_coarray = true;
6869 needs_caf_sync = needs_caf_sync
6870 || caf_attr.coarray_comp || !caf_refs_comp;
6871 }
ffaf9305 6872
34d9d749
AV
6873 if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
6874 && expr3_len != NULL_TREE)
6875 {
6876 /* Arrays need to have a _len set before the array
6877 descriptor is filled. */
6878 gfc_add_modify (&block, al_len,
6879 fold_convert (TREE_TYPE (al_len), expr3_len));
6880 /* Prevent setting the length twice. */
6881 al_len_needs_set = false;
6882 }
afbc5ae8 6883 else if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
323c5722 6884 && code->ext.alloc.ts.u.cl->length)
afbc5ae8
PT
6885 {
6886 /* Cover the cases where a string length is explicitly
6887 specified by a type spec for deferred length character
6888 arrays or unlimited polymorphic objects without a
6889 source= or mold= expression. */
6890 gfc_init_se (&se_sz, NULL);
6891 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
69aaea06 6892 gfc_add_block_to_block (&block, &se_sz.pre);
afbc5ae8
PT
6893 gfc_add_modify (&block, al_len,
6894 fold_convert (TREE_TYPE (al_len),
6895 se_sz.expr));
6896 al_len_needs_set = false;
6897 }
34d9d749 6898 }
6de9cd9a 6899
90cf3ecc 6900 gfc_add_block_to_block (&block, &se.pre);
cf2b3c22 6901
8f992d64
DC
6902 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
6903 if (code->expr1)
6904 {
5d81ddd0 6905 tmp = build1_v (GOTO_EXPR, label_errmsg);
8f992d64 6906 parm = fold_build2_loc (input_location, NE_EXPR,
63ee5404 6907 logical_type_node, stat,
8f992d64
DC
6908 build_int_cst (TREE_TYPE (stat), 0));
6909 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
ed9c79e1
JJ
6910 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
6911 tmp, build_empty_stmt (input_location));
8f992d64
DC
6912 gfc_add_expr_to_block (&block, tmp);
6913 }
8b704316 6914
574284e9
AV
6915 /* Set the vptr only when no source= is set. When source= is set, then
6916 the trans_assignment below will set the vptr. */
6917 if (al_vptr != NULL_TREE && (!code->expr3 || code->expr3->mold))
c49ea23d 6918 {
34d9d749
AV
6919 if (expr3_vptr != NULL_TREE)
6920 /* The vtab is already known, so just assign it. */
6921 gfc_add_modify (&block, al_vptr,
6922 fold_convert (TREE_TYPE (al_vptr), expr3_vptr));
c49ea23d
PT
6923 else
6924 {
6925 /* VPTR is fixed at compile time. */
6926 gfc_symbol *vtab;
6927 gfc_typespec *ts;
34d9d749 6928
c49ea23d 6929 if (code->expr3)
34d9d749
AV
6930 /* Although expr3 is pre-evaluated above, it may happen,
6931 that for arrays or in mold= cases the pre-evaluation
6932 was not successful. In these rare cases take the vtab
6933 from the typespec of expr3 here. */
c49ea23d 6934 ts = &code->expr3->ts;
34d9d749
AV
6935 else if (code->ext.alloc.ts.type == BT_DERIVED || upoly_expr)
6936 /* The alloc_type_spec gives the type to allocate or the
6937 al is unlimited polymorphic, which enforces the use of
6938 an alloc_type_spec that is not necessarily a BT_DERIVED. */
c49ea23d 6939 ts = &code->ext.alloc.ts;
c49ea23d 6940 else
34d9d749
AV
6941 /* Prepare for setting the vtab as declared. */
6942 ts = &expr->ts;
6943
6944 vtab = gfc_find_vtab (ts);
6945 gcc_assert (vtab);
6946 tmp = gfc_build_addr_expr (NULL_TREE,
6947 gfc_get_symbol_decl (vtab));
6948 gfc_add_modify (&block, al_vptr,
6949 fold_convert (TREE_TYPE (al_vptr), tmp));
c49ea23d 6950 }
c49ea23d
PT
6951 }
6952
34d9d749
AV
6953 /* Add assignment for string length. */
6954 if (al_len != NULL_TREE && al_len_needs_set)
6955 {
6956 if (expr3_len != NULL_TREE)
6957 {
6958 gfc_add_modify (&block, al_len,
6959 fold_convert (TREE_TYPE (al_len),
6960 expr3_len));
6961 /* When tmp_expr3_len_flag is set, then expr3_len is
6962 abused to carry the length information from the
6963 alloc_type. Clear it to prevent setting incorrect len
6964 information in future loop iterations. */
6965 if (tmp_expr3_len_flag)
6966 /* No need to reset tmp_expr3_len_flag, because the
67914693 6967 presence of an expr3 cannot change within in the
34d9d749
AV
6968 loop. */
6969 expr3_len = NULL_TREE;
6970 }
6971 else if (code->ext.alloc.ts.type == BT_CHARACTER
323c5722 6972 && code->ext.alloc.ts.u.cl->length)
34d9d749
AV
6973 {
6974 /* Cover the cases where a string length is explicitly
6975 specified by a type spec for deferred length character
6976 arrays or unlimited polymorphic objects without a
6977 source= or mold= expression. */
69aaea06
AV
6978 if (expr3_esize == NULL_TREE || code->ext.alloc.ts.kind != 1)
6979 {
6980 gfc_init_se (&se_sz, NULL);
6981 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6982 gfc_add_block_to_block (&block, &se_sz.pre);
6983 gfc_add_modify (&block, al_len,
6984 fold_convert (TREE_TYPE (al_len),
6985 se_sz.expr));
6986 }
6987 else
6988 gfc_add_modify (&block, al_len,
6989 fold_convert (TREE_TYPE (al_len),
6990 expr3_esize));
34d9d749
AV
6991 }
6992 else
6993 /* No length information needed, because type to allocate
6994 has no length. Set _len to 0. */
6995 gfc_add_modify (&block, al_len,
6996 fold_convert (TREE_TYPE (al_len),
6997 integer_zero_node));
6998 }
cc03bf7a
AV
6999
7000 init_expr = NULL;
64e56ab0 7001 if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD)
cf2b3c22 7002 {
db7ffcab 7003 /* Initialization via SOURCE block (or static default initializer).
574284e9
AV
7004 Switch off automatic reallocation since we have just done the
7005 ALLOCATE. */
7006 int realloc_lhs = flag_realloc_lhs;
7007 gfc_expr *init_expr = gfc_expr_to_initialize (expr);
7008 gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3);
7009 flag_realloc_lhs = 0;
21ced277 7010 tmp = gfc_trans_assignment (init_expr, rhs, true, false, true,
574284e9
AV
7011 false);
7012 flag_realloc_lhs = realloc_lhs;
7013 /* Free the expression allocated for init_expr. */
7014 gfc_free_expr (init_expr);
7015 if (rhs != e3rhs)
7016 gfc_free_expr (rhs);
f43085aa
JW
7017 gfc_add_expr_to_block (&block, tmp);
7018 }
5bab4c96
PT
7019 /* Set KIND and LEN PDT components and allocate those that are
7020 parameterized. */
7021 else if (expr->ts.type == BT_DERIVED
7022 && expr->ts.u.derived->attr.pdt_type)
7023 {
7024 if (code->expr3 && code->expr3->param_list)
7025 param_list = code->expr3->param_list;
7026 else if (expr->param_list)
7027 param_list = expr->param_list;
7028 else
7029 param_list = expr->symtree->n.sym->param_list;
7030 tmp = gfc_allocate_pdt_comp (expr->ts.u.derived, se.expr,
7031 expr->rank, param_list);
7032 gfc_add_expr_to_block (&block, tmp);
7033 }
7034 /* Ditto for CLASS expressions. */
7035 else if (expr->ts.type == BT_CLASS
7036 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type)
7037 {
7038 if (code->expr3 && code->expr3->param_list)
7039 param_list = code->expr3->param_list;
7040 else if (expr->param_list)
7041 param_list = expr->param_list;
7042 else
7043 param_list = expr->symtree->n.sym->param_list;
7044 tmp = gfc_allocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
7045 se.expr, expr->rank, param_list);
7046 gfc_add_expr_to_block (&block, tmp);
7047 }
574284e9
AV
7048 else if (code->expr3 && code->expr3->mold
7049 && code->expr3->ts.type == BT_CLASS)
50f30801 7050 {
574284e9
AV
7051 /* Use class_init_assign to initialize expr. */
7052 gfc_code *ini;
7053 ini = gfc_get_code (EXEC_INIT_ASSIGN);
4afe8252 7054 ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr, true);
574284e9
AV
7055 tmp = gfc_trans_class_init_assign (ini);
7056 gfc_free_statements (ini);
b6ff8128 7057 gfc_add_expr_to_block (&block, tmp);
50f30801 7058 }
cc03bf7a
AV
7059 else if ((init_expr = allocate_get_initializer (code, expr)))
7060 {
7061 /* Use class_init_assign to initialize expr. */
7062 gfc_code *ini;
7063 int realloc_lhs = flag_realloc_lhs;
7064 ini = gfc_get_code (EXEC_INIT_ASSIGN);
7065 ini->expr1 = gfc_expr_to_initialize (expr);
7066 ini->expr2 = init_expr;
7067 flag_realloc_lhs = 0;
7068 tmp= gfc_trans_init_assign (ini);
7069 flag_realloc_lhs = realloc_lhs;
7070 gfc_free_statements (ini);
7071 /* Init_expr is freeed by above free_statements, just need to null
7072 it here. */
7073 init_expr = NULL;
7074 gfc_add_expr_to_block (&block, tmp);
7075 }
f43085aa 7076
de91486c
AV
7077 /* Nullify all pointers in derived type coarrays. This registers a
7078 token for them which allows their allocation. */
7079 if (is_coarray)
7080 {
7081 gfc_symbol *type = NULL;
7082 symbol_attribute caf_attr;
7083 int rank = 0;
7084 if (code->ext.alloc.ts.type == BT_DERIVED
7085 && code->ext.alloc.ts.u.derived->attr.pointer_comp)
7086 {
7087 type = code->ext.alloc.ts.u.derived;
7088 rank = type->attr.dimension ? type->as->rank : 0;
7089 gfc_clear_attr (&caf_attr);
7090 }
7091 else if (expr->ts.type == BT_DERIVED
7092 && expr->ts.u.derived->attr.pointer_comp)
7093 {
7094 type = expr->ts.u.derived;
7095 rank = expr->rank;
7096 caf_attr = gfc_caf_attr (expr, true);
7097 }
7098
7099 /* Initialize the tokens of pointer components in derived type
7100 coarrays. */
7101 if (type)
7102 {
7103 tmp = (caf_attr.codimension && !caf_attr.dimension)
7104 ? gfc_conv_descriptor_data_get (se.expr) : se.expr;
7105 tmp = gfc_nullify_alloc_comp (type, tmp, rank,
7106 GFC_STRUCTURE_CAF_MODE_IN_COARRAY);
7107 gfc_add_expr_to_block (&block, tmp);
7108 }
7109 }
7110
574284e9 7111 gfc_free_expr (expr);
34d9d749 7112 } // for-loop
6de9cd9a 7113
db7ffcab
AV
7114 if (e3rhs)
7115 {
7116 if (newsym)
7117 {
7118 gfc_free_symbol (newsym->n.sym);
7119 XDELETE (newsym);
7120 }
7121 gfc_free_expr (e3rhs);
7122 }
5d81ddd0 7123 /* STAT. */
a513927a 7124 if (code->expr1)
6de9cd9a 7125 {
8f992d64 7126 tmp = build1_v (LABEL_EXPR, label_errmsg);
6de9cd9a 7127 gfc_add_expr_to_block (&block, tmp);
6de9cd9a
DN
7128 }
7129
5d81ddd0
TB
7130 /* ERRMSG - only useful if STAT is present. */
7131 if (code->expr1 && code->expr2)
3759634f 7132 {
3759634f 7133 const char *msg = "Attempt to allocate an allocated object";
871dbb61
HA
7134 const char *oommsg = "Insufficient virtual memory";
7135 tree slen, dlen, errmsg_str, oom_str, oom_loc;
5d81ddd0 7136 stmtblock_t errmsg_block;
3759634f 7137
5d81ddd0 7138 gfc_init_block (&errmsg_block);
3759634f 7139
5d81ddd0
TB
7140 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
7141 gfc_add_modify (&errmsg_block, errmsg_str,
3759634f
SK
7142 gfc_build_addr_expr (pchar_type_node,
7143 gfc_build_localized_cstring_const (msg)));
7144
f622221a 7145 slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
3759634f 7146 dlen = gfc_get_expr_charlen (code->expr2);
34d9d749
AV
7147 slen = fold_build2_loc (input_location, MIN_EXPR,
7148 TREE_TYPE (slen), dlen, slen);
3759634f 7149
34d9d749
AV
7150 gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
7151 code->expr2->ts.kind,
7152 slen, errmsg_str,
7153 gfc_default_character_kind);
5d81ddd0 7154 dlen = gfc_finish_block (&errmsg_block);
3759634f 7155
871dbb61
HA
7156 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7157 stat, build_int_cst (TREE_TYPE (stat),
7158 LIBERROR_ALLOCATION));
7159
7160 tmp = build3_v (COND_EXPR, tmp,
7161 dlen, build_empty_stmt (input_location));
7162
7163 gfc_add_expr_to_block (&block, tmp);
7164
7165 oom_str = gfc_create_var (pchar_type_node, "OOMMSG");
7166 oom_loc = gfc_build_localized_cstring_const (oommsg);
7167 gfc_add_modify (&errmsg_block, oom_str,
7168 gfc_build_addr_expr (pchar_type_node, oom_loc));
7169
7170 slen = build_int_cst (gfc_charlen_type_node, strlen (oommsg));
7171 dlen = gfc_get_expr_charlen (code->expr2);
7172 slen = fold_build2_loc (input_location, MIN_EXPR,
7173 TREE_TYPE (slen), dlen, slen);
7174
7175 gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
7176 code->expr2->ts.kind,
7177 slen, oom_str,
7178 gfc_default_character_kind);
7179 dlen = gfc_finish_block (&errmsg_block);
7180
7181 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7182 stat, build_int_cst (TREE_TYPE (stat),
7183 LIBERROR_NO_MEMORY));
3759634f 7184
34d9d749
AV
7185 tmp = build3_v (COND_EXPR, tmp,
7186 dlen, build_empty_stmt (input_location));
3759634f
SK
7187
7188 gfc_add_expr_to_block (&block, tmp);
7189 }
7190
8f992d64
DC
7191 /* STAT block. */
7192 if (code->expr1)
7193 {
5d81ddd0
TB
7194 if (TREE_USED (label_finish))
7195 {
7196 tmp = build1_v (LABEL_EXPR, label_finish);
7197 gfc_add_expr_to_block (&block, tmp);
7198 }
7199
8f992d64
DC
7200 gfc_init_se (&se, NULL);
7201 gfc_conv_expr_lhs (&se, code->expr1);
7202 tmp = convert (TREE_TYPE (se.expr), stat);
7203 gfc_add_modify (&block, se.expr, tmp);
7204 }
7205
525a5e33 7206 if (needs_caf_sync)
ffaf9305
AV
7207 {
7208 /* Add a sync all after the allocation has been executed. */
0f09fc8a 7209 tree zero_size = build_zero_cst (size_type_node);
ffaf9305
AV
7210 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
7211 3, null_pointer_node, null_pointer_node,
0f09fc8a 7212 zero_size);
ffaf9305
AV
7213 gfc_add_expr_to_block (&post, tmp);
7214 }
7215
90cf3ecc
PT
7216 gfc_add_block_to_block (&block, &se.post);
7217 gfc_add_block_to_block (&block, &post);
1312bb90
PT
7218 if (code->expr3 && code->expr3->must_finalize)
7219 gfc_add_block_to_block (&block, &final_block);
90cf3ecc 7220
6de9cd9a
DN
7221 return gfc_finish_block (&block);
7222}
7223
7224
3759634f
SK
7225/* Translate a DEALLOCATE statement. */
7226
6de9cd9a 7227tree
3759634f 7228gfc_trans_deallocate (gfc_code *code)
6de9cd9a
DN
7229{
7230 gfc_se se;
7231 gfc_alloc *al;
5d81ddd0
TB
7232 tree apstat, pstat, stat, errmsg, errlen, tmp;
7233 tree label_finish, label_errmsg;
6de9cd9a
DN
7234 stmtblock_t block;
7235
5d81ddd0
TB
7236 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
7237 label_finish = label_errmsg = NULL_TREE;
3759634f 7238
6de9cd9a
DN
7239 gfc_start_block (&block);
7240
3759634f
SK
7241 /* Count the number of failed deallocations. If deallocate() was
7242 called with STAT= , then set STAT to the count. If deallocate
7243 was called with ERRMSG, then set ERRMG to a string. */
5d81ddd0 7244 if (code->expr1)
364667a1
SK
7245 {
7246 tree gfc_int4_type_node = gfc_get_int_type (4);
7247
364667a1 7248 stat = gfc_create_var (gfc_int4_type_node, "stat");
628c189e 7249 pstat = gfc_build_addr_expr (NULL_TREE, stat);
364667a1 7250
5d81ddd0
TB
7251 /* GOTO destinations. */
7252 label_errmsg = gfc_build_label_decl (NULL_TREE);
7253 label_finish = gfc_build_label_decl (NULL_TREE);
7254 TREE_USED (label_finish) = 0;
7255 }
364667a1 7256
5d81ddd0
TB
7257 /* Set ERRMSG - only needed if STAT is available. */
7258 if (code->expr1 && code->expr2)
7259 {
7260 gfc_init_se (&se, NULL);
7261 se.want_pointer = 1;
7262 gfc_conv_expr_lhs (&se, code->expr2);
7263 errmsg = se.expr;
7264 errlen = se.string_length;
364667a1 7265 }
364667a1 7266
cf2b3c22 7267 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6de9cd9a 7268 {
0d87fa8c 7269 gfc_expr *expr = gfc_copy_expr (al->expr);
ba85c8c3
AV
7270 bool is_coarray = false, is_coarray_array = false;
7271 int caf_mode = 0;
7272
6e45f57b 7273 gcc_assert (expr->expr_type == EXPR_VARIABLE);
6de9cd9a 7274
0d87fa8c
JW
7275 if (expr->ts.type == BT_CLASS)
7276 gfc_add_data_component (expr);
7277
6de9cd9a
DN
7278 gfc_init_se (&se, NULL);
7279 gfc_start_block (&se.pre);
7280
7281 se.want_pointer = 1;
7282 se.descriptor_only = 1;
7283 gfc_conv_expr (&se, expr);
7284
5bab4c96
PT
7285 /* Deallocate PDT components that are parameterized. */
7286 tmp = NULL;
7287 if (expr->ts.type == BT_DERIVED
7288 && expr->ts.u.derived->attr.pdt_type
7289 && expr->symtree->n.sym->param_list)
7290 tmp = gfc_deallocate_pdt_comp (expr->ts.u.derived, se.expr, expr->rank);
7291 else if (expr->ts.type == BT_CLASS
7292 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type
7293 && expr->symtree->n.sym->param_list)
7294 tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
7295 se.expr, expr->rank);
7296
7297 if (tmp)
7298 gfc_add_expr_to_block (&block, tmp);
7299
de91486c
AV
7300 if (flag_coarray == GFC_FCOARRAY_LIB
7301 || flag_coarray == GFC_FCOARRAY_SINGLE)
ba85c8c3
AV
7302 {
7303 bool comp_ref;
7304 symbol_attribute caf_attr = gfc_caf_attr (expr, false, &comp_ref);
7305 if (caf_attr.codimension)
7306 {
7307 is_coarray = true;
7308 is_coarray_array = caf_attr.dimension || !comp_ref
7309 || caf_attr.coarray_comp;
7310
de91486c
AV
7311 if (flag_coarray == GFC_FCOARRAY_LIB)
7312 /* When the expression to deallocate is referencing a
7313 component, then only deallocate it, but do not
7314 deregister. */
7315 caf_mode = GFC_STRUCTURE_CAF_MODE_IN_COARRAY
7316 | (comp_ref && !caf_attr.coarray_comp
7317 ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY : 0);
ba85c8c3
AV
7318 }
7319 }
ba85c8c3
AV
7320
7321 if (expr->rank || is_coarray_array)
2c807128 7322 {
ec6a7096
PT
7323 gfc_ref *ref;
7324
ba85c8c3
AV
7325 if (gfc_bt_struct (expr->ts.type)
7326 && expr->ts.u.derived->attr.alloc_comp
ef292537 7327 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5046aff5 7328 {
2c807128 7329 gfc_ref *last = NULL;
ec6a7096 7330
2c807128
JW
7331 for (ref = expr->ref; ref; ref = ref->next)
7332 if (ref->type == REF_COMPONENT)
7333 last = ref;
7334
7335 /* Do not deallocate the components of a derived type
34d9d749 7336 ultimate pointer component. */
2c807128
JW
7337 if (!(last && last->u.c.component->attr.pointer)
7338 && !(!last && expr->symtree->n.sym->attr.pointer))
7339 {
ba85c8c3 7340 if (is_coarray && expr->rank == 0
eb401400
AV
7341 && (!last || !last->u.c.component->attr.dimension)
7342 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
ba85c8c3
AV
7343 {
7344 /* Add the ref to the data member only, when this is not
7345 a regular array or deallocate_alloc_comp will try to
7346 add another one. */
7347 tmp = gfc_conv_descriptor_data_get (se.expr);
7348 }
7349 else
7350 tmp = se.expr;
7351 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp,
7352 expr->rank, caf_mode);
2c807128
JW
7353 gfc_add_expr_to_block (&se.pre, tmp);
7354 }
5046aff5 7355 }
ec6a7096
PT
7356
7357 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
7358 {
ba85c8c3
AV
7359 gfc_coarray_deregtype caf_dtype;
7360
7361 if (is_coarray)
7362 caf_dtype = gfc_caf_is_dealloc_only (caf_mode)
7363 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
7364 : GFC_CAF_COARRAY_DEREGISTER;
7365 else
7366 caf_dtype = GFC_CAF_COARRAY_NOCOARRAY;
39da5866
AV
7367 tmp = gfc_deallocate_with_status (se.expr, pstat, errmsg, errlen,
7368 label_finish, false, expr,
7369 caf_dtype);
ec6a7096
PT
7370 gfc_add_expr_to_block (&se.pre, tmp);
7371 }
7372 else if (TREE_CODE (se.expr) == COMPONENT_REF
7373 && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE
7374 && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr)))
7375 == RECORD_TYPE)
7376 {
e53b6e56 7377 /* class.cc(finalize_component) generates these, when a
ec6a7096
PT
7378 finalizable entity has a non-allocatable derived type array
7379 component, which has allocatable components. Obtain the
7380 derived type of the array and deallocate the allocatable
7381 components. */
7382 for (ref = expr->ref; ref; ref = ref->next)
7383 {
7384 if (ref->u.c.component->attr.dimension
7385 && ref->u.c.component->ts.type == BT_DERIVED)
7386 break;
7387 }
7388
7389 if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp
7390 && !gfc_is_finalizable (ref->u.c.component->ts.u.derived,
7391 NULL))
7392 {
7393 tmp = gfc_deallocate_alloc_comp
7394 (ref->u.c.component->ts.u.derived,
7395 se.expr, expr->rank);
7396 gfc_add_expr_to_block (&se.pre, tmp);
7397 }
7398 }
7399
4fb5478c 7400 if (al->expr->ts.type == BT_CLASS)
34d9d749
AV
7401 {
7402 gfc_reset_vptr (&se.pre, al->expr);
7403 if (UNLIMITED_POLY (al->expr)
7404 || (al->expr->ts.type == BT_DERIVED
7405 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
7406 /* Clear _len, too. */
7407 gfc_reset_len (&se.pre, al->expr);
7408 }
5046aff5 7409 }
6de9cd9a
DN
7410 else
7411 {
ba85c8c3
AV
7412 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, label_finish,
7413 false, al->expr,
7414 al->expr->ts, is_coarray);
54200abb
RG
7415 gfc_add_expr_to_block (&se.pre, tmp);
7416
0d87fa8c 7417 /* Set to zero after deallocation. */
bc98ed60
TB
7418 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7419 se.expr,
7420 build_int_cst (TREE_TYPE (se.expr), 0));
0d87fa8c 7421 gfc_add_expr_to_block (&se.pre, tmp);
8b704316 7422
0d87fa8c 7423 if (al->expr->ts.type == BT_CLASS)
34d9d749
AV
7424 {
7425 gfc_reset_vptr (&se.pre, al->expr);
7426 if (UNLIMITED_POLY (al->expr)
7427 || (al->expr->ts.type == BT_DERIVED
7428 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
7429 /* Clear _len, too. */
7430 gfc_reset_len (&se.pre, al->expr);
7431 }
6de9cd9a 7432 }
364667a1 7433
5d81ddd0 7434 if (code->expr1)
364667a1 7435 {
5d81ddd0
TB
7436 tree cond;
7437
63ee5404 7438 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
5d81ddd0
TB
7439 build_int_cst (TREE_TYPE (stat), 0));
7440 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
ed9c79e1 7441 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
5d81ddd0
TB
7442 build1_v (GOTO_EXPR, label_errmsg),
7443 build_empty_stmt (input_location));
7444 gfc_add_expr_to_block (&se.pre, tmp);
364667a1
SK
7445 }
7446
6de9cd9a
DN
7447 tmp = gfc_finish_block (&se.pre);
7448 gfc_add_expr_to_block (&block, tmp);
0d87fa8c 7449 gfc_free_expr (expr);
364667a1
SK
7450 }
7451
a513927a 7452 if (code->expr1)
364667a1 7453 {
5d81ddd0
TB
7454 tmp = build1_v (LABEL_EXPR, label_errmsg);
7455 gfc_add_expr_to_block (&block, tmp);
6de9cd9a
DN
7456 }
7457
5d81ddd0
TB
7458 /* Set ERRMSG - only needed if STAT is available. */
7459 if (code->expr1 && code->expr2)
3759634f 7460 {
3759634f 7461 const char *msg = "Attempt to deallocate an unallocated object";
5d81ddd0
TB
7462 stmtblock_t errmsg_block;
7463 tree errmsg_str, slen, dlen, cond;
3759634f 7464
5d81ddd0 7465 gfc_init_block (&errmsg_block);
3759634f 7466
5d81ddd0
TB
7467 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
7468 gfc_add_modify (&errmsg_block, errmsg_str,
3759634f
SK
7469 gfc_build_addr_expr (pchar_type_node,
7470 gfc_build_localized_cstring_const (msg)));
f622221a 7471 slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
3759634f 7472 dlen = gfc_get_expr_charlen (code->expr2);
3759634f 7473
5d81ddd0
TB
7474 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
7475 slen, errmsg_str, gfc_default_character_kind);
7476 tmp = gfc_finish_block (&errmsg_block);
3759634f 7477
63ee5404 7478 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
5d81ddd0
TB
7479 build_int_cst (TREE_TYPE (stat), 0));
7480 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
ed9c79e1 7481 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
5d81ddd0 7482 build_empty_stmt (input_location));
3759634f 7483
5d81ddd0
TB
7484 gfc_add_expr_to_block (&block, tmp);
7485 }
3759634f 7486
5d81ddd0
TB
7487 if (code->expr1 && TREE_USED (label_finish))
7488 {
7489 tmp = build1_v (LABEL_EXPR, label_finish);
3759634f
SK
7490 gfc_add_expr_to_block (&block, tmp);
7491 }
7492
5d81ddd0
TB
7493 /* Set STAT. */
7494 if (code->expr1)
7495 {
7496 gfc_init_se (&se, NULL);
7497 gfc_conv_expr_lhs (&se, code->expr1);
7498 tmp = convert (TREE_TYPE (se.expr), stat);
7499 gfc_add_modify (&block, se.expr, tmp);
7500 }
7501
6de9cd9a
DN
7502 return gfc_finish_block (&block);
7503}
7504
d2886bc7 7505#include "gt-fortran-trans-stmt.h"