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