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