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