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