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