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