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