2018-01-13 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-array.c
blob0cf1831802b66692a6920b6ff49dcc7beee7420b
1 /* Array translation routines
2 Copyright (C) 2002-2018 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
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.
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.
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/>. */
22 /* trans-array.c-- Various array related code, including scalarization,
23 allocation, initialization and other support routines. */
25 /* How the scalarizer works.
26 In gfortran, array expressions use the same core routines as scalar
27 expressions.
28 First, a Scalarization State (SS) chain is built. This is done by walking
29 the expression tree, and building a linear list of the terms in the
30 expression. As the tree is walked, scalar subexpressions are translated.
32 The scalarization parameters are stored in a gfc_loopinfo structure.
33 First the start and stride of each term is calculated by
34 gfc_conv_ss_startstride. During this process the expressions for the array
35 descriptors and data pointers are also translated.
37 If the expression is an assignment, we must then resolve any dependencies.
38 In Fortran all the rhs values of an assignment must be evaluated before
39 any assignments take place. This can require a temporary array to store the
40 values. We also require a temporary when we are passing array expressions
41 or vector subscripts as procedure parameters.
43 Array sections are passed without copying to a temporary. These use the
44 scalarizer to determine the shape of the section. The flag
45 loop->array_parameter tells the scalarizer that the actual values and loop
46 variables will not be required.
48 The function gfc_conv_loop_setup generates the scalarization setup code.
49 It determines the range of the scalarizing loop variables. If a temporary
50 is required, this is created and initialized. Code for scalar expressions
51 taken outside the loop is also generated at this time. Next the offset and
52 scaling required to translate from loop variables to array indices for each
53 term is calculated.
55 A call to gfc_start_scalarized_body marks the start of the scalarized
56 expression. This creates a scope and declares the loop variables. Before
57 calling this gfc_make_ss_chain_used must be used to indicate which terms
58 will be used inside this loop.
60 The scalar gfc_conv_* functions are then used to build the main body of the
61 scalarization loop. Scalarization loop variables and precalculated scalar
62 values are automatically substituted. Note that gfc_advance_se_ss_chain
63 must be used, rather than changing the se->ss directly.
65 For assignment expressions requiring a temporary two sub loops are
66 generated. The first stores the result of the expression in the temporary,
67 the second copies it to the result. A call to
68 gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
69 the start of the copying loop. The temporary may be less than full rank.
71 Finally gfc_trans_scalarizing_loops is called to generate the implicit do
72 loops. The loops are added to the pre chain of the loopinfo. The post
73 chain may still contain cleanup code.
75 After the loop code has been added into its parent scope gfc_cleanup_loop
76 is called to free all the SS allocated by the scalarizer. */
78 #include "config.h"
79 #include "system.h"
80 #include "coretypes.h"
81 #include "options.h"
82 #include "tree.h"
83 #include "gfortran.h"
84 #include "gimple-expr.h"
85 #include "trans.h"
86 #include "fold-const.h"
87 #include "constructor.h"
88 #include "trans-types.h"
89 #include "trans-array.h"
90 #include "trans-const.h"
91 #include "dependency.h"
93 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
95 /* The contents of this structure aren't actually used, just the address. */
96 static gfc_ss gfc_ss_terminator_var;
97 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
100 static tree
101 gfc_array_dataptr_type (tree desc)
103 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
107 /* Build expressions to access the members of an array descriptor.
108 It's surprisingly easy to mess up here, so never access
109 an array descriptor by "brute force", always use these
110 functions. This also avoids problems if we change the format
111 of an array descriptor.
113 To understand these magic numbers, look at the comments
114 before gfc_build_array_type() in trans-types.c.
116 The code within these defines should be the only code which knows the format
117 of an array descriptor.
119 Any code just needing to read obtain the bounds of an array should use
120 gfc_conv_array_* rather than the following functions as these will return
121 know constant values, and work with arrays which do not have descriptors.
123 Don't forget to #undef these! */
125 #define DATA_FIELD 0
126 #define OFFSET_FIELD 1
127 #define DTYPE_FIELD 2
128 #define SPAN_FIELD 3
129 #define DIMENSION_FIELD 4
130 #define CAF_TOKEN_FIELD 5
132 #define STRIDE_SUBFIELD 0
133 #define LBOUND_SUBFIELD 1
134 #define UBOUND_SUBFIELD 2
136 /* This provides READ-ONLY access to the data field. The field itself
137 doesn't have the proper type. */
139 tree
140 gfc_conv_descriptor_data_get (tree desc)
142 tree field, type, t;
144 type = TREE_TYPE (desc);
145 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
147 field = TYPE_FIELDS (type);
148 gcc_assert (DATA_FIELD == 0);
150 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
151 field, NULL_TREE);
152 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
154 return t;
157 /* This provides WRITE access to the data field.
159 TUPLES_P is true if we are generating tuples.
161 This function gets called through the following macros:
162 gfc_conv_descriptor_data_set
163 gfc_conv_descriptor_data_set. */
165 void
166 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
168 tree field, type, t;
170 type = TREE_TYPE (desc);
171 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
173 field = TYPE_FIELDS (type);
174 gcc_assert (DATA_FIELD == 0);
176 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
177 field, NULL_TREE);
178 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
182 /* This provides address access to the data field. This should only be
183 used by array allocation, passing this on to the runtime. */
185 tree
186 gfc_conv_descriptor_data_addr (tree desc)
188 tree field, type, t;
190 type = TREE_TYPE (desc);
191 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
193 field = TYPE_FIELDS (type);
194 gcc_assert (DATA_FIELD == 0);
196 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
197 field, NULL_TREE);
198 return gfc_build_addr_expr (NULL_TREE, t);
201 static tree
202 gfc_conv_descriptor_offset (tree desc)
204 tree type;
205 tree field;
207 type = TREE_TYPE (desc);
208 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
210 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
211 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
213 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
214 desc, field, NULL_TREE);
217 tree
218 gfc_conv_descriptor_offset_get (tree desc)
220 return gfc_conv_descriptor_offset (desc);
223 void
224 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
225 tree value)
227 tree t = gfc_conv_descriptor_offset (desc);
228 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
232 tree
233 gfc_conv_descriptor_dtype (tree desc)
235 tree field;
236 tree type;
238 type = TREE_TYPE (desc);
239 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
241 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
242 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
244 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
245 desc, field, NULL_TREE);
248 static tree
249 gfc_conv_descriptor_span (tree desc)
251 tree type;
252 tree field;
254 type = TREE_TYPE (desc);
255 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
257 field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
258 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
260 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
261 desc, field, NULL_TREE);
264 tree
265 gfc_conv_descriptor_span_get (tree desc)
267 return gfc_conv_descriptor_span (desc);
270 void
271 gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc,
272 tree value)
274 tree t = gfc_conv_descriptor_span (desc);
275 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
279 tree
280 gfc_conv_descriptor_rank (tree desc)
282 tree tmp;
283 tree dtype;
285 dtype = gfc_conv_descriptor_dtype (desc);
286 tmp = build_int_cst (TREE_TYPE (dtype), GFC_DTYPE_RANK_MASK);
287 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (dtype),
288 dtype, tmp);
289 return fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
293 tree
294 gfc_get_descriptor_dimension (tree desc)
296 tree type, field;
298 type = TREE_TYPE (desc);
299 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
301 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
302 gcc_assert (field != NULL_TREE
303 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
304 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
306 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
307 desc, field, NULL_TREE);
311 static tree
312 gfc_conv_descriptor_dimension (tree desc, tree dim)
314 tree tmp;
316 tmp = gfc_get_descriptor_dimension (desc);
318 return gfc_build_array_ref (tmp, dim, NULL);
322 tree
323 gfc_conv_descriptor_token (tree desc)
325 tree type;
326 tree field;
328 type = TREE_TYPE (desc);
329 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
330 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
331 field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
333 /* Should be a restricted pointer - except in the finalization wrapper. */
334 gcc_assert (field != NULL_TREE
335 && (TREE_TYPE (field) == prvoid_type_node
336 || TREE_TYPE (field) == pvoid_type_node));
338 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
339 desc, field, NULL_TREE);
343 static tree
344 gfc_conv_descriptor_stride (tree desc, tree dim)
346 tree tmp;
347 tree field;
349 tmp = gfc_conv_descriptor_dimension (desc, dim);
350 field = TYPE_FIELDS (TREE_TYPE (tmp));
351 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
352 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
354 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
355 tmp, field, NULL_TREE);
356 return tmp;
359 tree
360 gfc_conv_descriptor_stride_get (tree desc, tree dim)
362 tree type = TREE_TYPE (desc);
363 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
364 if (integer_zerop (dim)
365 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
366 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
367 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
368 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
369 return gfc_index_one_node;
371 return gfc_conv_descriptor_stride (desc, dim);
374 void
375 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
376 tree dim, tree value)
378 tree t = gfc_conv_descriptor_stride (desc, dim);
379 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
382 static tree
383 gfc_conv_descriptor_lbound (tree desc, tree dim)
385 tree tmp;
386 tree field;
388 tmp = gfc_conv_descriptor_dimension (desc, dim);
389 field = TYPE_FIELDS (TREE_TYPE (tmp));
390 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
391 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
393 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
394 tmp, field, NULL_TREE);
395 return tmp;
398 tree
399 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
401 return gfc_conv_descriptor_lbound (desc, dim);
404 void
405 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
406 tree dim, tree value)
408 tree t = gfc_conv_descriptor_lbound (desc, dim);
409 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
412 static tree
413 gfc_conv_descriptor_ubound (tree desc, tree dim)
415 tree tmp;
416 tree field;
418 tmp = gfc_conv_descriptor_dimension (desc, dim);
419 field = TYPE_FIELDS (TREE_TYPE (tmp));
420 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
421 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
423 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
424 tmp, field, NULL_TREE);
425 return tmp;
428 tree
429 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
431 return gfc_conv_descriptor_ubound (desc, dim);
434 void
435 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
436 tree dim, tree value)
438 tree t = gfc_conv_descriptor_ubound (desc, dim);
439 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
442 /* Build a null array descriptor constructor. */
444 tree
445 gfc_build_null_descriptor (tree type)
447 tree field;
448 tree tmp;
450 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
451 gcc_assert (DATA_FIELD == 0);
452 field = TYPE_FIELDS (type);
454 /* Set a NULL data pointer. */
455 tmp = build_constructor_single (type, field, null_pointer_node);
456 TREE_CONSTANT (tmp) = 1;
457 /* All other fields are ignored. */
459 return tmp;
463 /* Modify a descriptor such that the lbound of a given dimension is the value
464 specified. This also updates ubound and offset accordingly. */
466 void
467 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
468 int dim, tree new_lbound)
470 tree offs, ubound, lbound, stride;
471 tree diff, offs_diff;
473 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
475 offs = gfc_conv_descriptor_offset_get (desc);
476 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
477 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
478 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
480 /* Get difference (new - old) by which to shift stuff. */
481 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
482 new_lbound, lbound);
484 /* Shift ubound and offset accordingly. This has to be done before
485 updating the lbound, as they depend on the lbound expression! */
486 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
487 ubound, diff);
488 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
489 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
490 diff, stride);
491 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
492 offs, offs_diff);
493 gfc_conv_descriptor_offset_set (block, desc, offs);
495 /* Finally set lbound to value we want. */
496 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
500 /* Obtain offsets for trans-types.c(gfc_get_array_descr_info). */
502 void
503 gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
504 tree *dtype_off, tree *dim_off,
505 tree *dim_size, tree *stride_suboff,
506 tree *lower_suboff, tree *upper_suboff)
508 tree field;
509 tree type;
511 type = TYPE_MAIN_VARIANT (desc_type);
512 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
513 *data_off = byte_position (field);
514 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
515 *dtype_off = byte_position (field);
516 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
517 *dim_off = byte_position (field);
518 type = TREE_TYPE (TREE_TYPE (field));
519 *dim_size = TYPE_SIZE_UNIT (type);
520 field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
521 *stride_suboff = byte_position (field);
522 field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
523 *lower_suboff = byte_position (field);
524 field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
525 *upper_suboff = byte_position (field);
529 /* Cleanup those #defines. */
531 #undef DATA_FIELD
532 #undef OFFSET_FIELD
533 #undef DTYPE_FIELD
534 #undef SPAN_FIELD
535 #undef DIMENSION_FIELD
536 #undef CAF_TOKEN_FIELD
537 #undef STRIDE_SUBFIELD
538 #undef LBOUND_SUBFIELD
539 #undef UBOUND_SUBFIELD
542 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
543 flags & 1 = Main loop body.
544 flags & 2 = temp copy loop. */
546 void
547 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
549 for (; ss != gfc_ss_terminator; ss = ss->next)
550 ss->info->useflags = flags;
554 /* Free a gfc_ss chain. */
556 void
557 gfc_free_ss_chain (gfc_ss * ss)
559 gfc_ss *next;
561 while (ss != gfc_ss_terminator)
563 gcc_assert (ss != NULL);
564 next = ss->next;
565 gfc_free_ss (ss);
566 ss = next;
571 static void
572 free_ss_info (gfc_ss_info *ss_info)
574 int n;
576 ss_info->refcount--;
577 if (ss_info->refcount > 0)
578 return;
580 gcc_assert (ss_info->refcount == 0);
582 switch (ss_info->type)
584 case GFC_SS_SECTION:
585 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
586 if (ss_info->data.array.subscript[n])
587 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
588 break;
590 default:
591 break;
594 free (ss_info);
598 /* Free a SS. */
600 void
601 gfc_free_ss (gfc_ss * ss)
603 free_ss_info (ss->info);
604 free (ss);
608 /* Creates and initializes an array type gfc_ss struct. */
610 gfc_ss *
611 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
613 gfc_ss *ss;
614 gfc_ss_info *ss_info;
615 int i;
617 ss_info = gfc_get_ss_info ();
618 ss_info->refcount++;
619 ss_info->type = type;
620 ss_info->expr = expr;
622 ss = gfc_get_ss ();
623 ss->info = ss_info;
624 ss->next = next;
625 ss->dimen = dimen;
626 for (i = 0; i < ss->dimen; i++)
627 ss->dim[i] = i;
629 return ss;
633 /* Creates and initializes a temporary type gfc_ss struct. */
635 gfc_ss *
636 gfc_get_temp_ss (tree type, tree string_length, int dimen)
638 gfc_ss *ss;
639 gfc_ss_info *ss_info;
640 int i;
642 ss_info = gfc_get_ss_info ();
643 ss_info->refcount++;
644 ss_info->type = GFC_SS_TEMP;
645 ss_info->string_length = string_length;
646 ss_info->data.temp.type = type;
648 ss = gfc_get_ss ();
649 ss->info = ss_info;
650 ss->next = gfc_ss_terminator;
651 ss->dimen = dimen;
652 for (i = 0; i < ss->dimen; i++)
653 ss->dim[i] = i;
655 return ss;
659 /* Creates and initializes a scalar type gfc_ss struct. */
661 gfc_ss *
662 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
664 gfc_ss *ss;
665 gfc_ss_info *ss_info;
667 ss_info = gfc_get_ss_info ();
668 ss_info->refcount++;
669 ss_info->type = GFC_SS_SCALAR;
670 ss_info->expr = expr;
672 ss = gfc_get_ss ();
673 ss->info = ss_info;
674 ss->next = next;
676 return ss;
680 /* Free all the SS associated with a loop. */
682 void
683 gfc_cleanup_loop (gfc_loopinfo * loop)
685 gfc_loopinfo *loop_next, **ploop;
686 gfc_ss *ss;
687 gfc_ss *next;
689 ss = loop->ss;
690 while (ss != gfc_ss_terminator)
692 gcc_assert (ss != NULL);
693 next = ss->loop_chain;
694 gfc_free_ss (ss);
695 ss = next;
698 /* Remove reference to self in the parent loop. */
699 if (loop->parent)
700 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
701 if (*ploop == loop)
703 *ploop = loop->next;
704 break;
707 /* Free non-freed nested loops. */
708 for (loop = loop->nested; loop; loop = loop_next)
710 loop_next = loop->next;
711 gfc_cleanup_loop (loop);
712 free (loop);
717 static void
718 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
720 int n;
722 for (; ss != gfc_ss_terminator; ss = ss->next)
724 ss->loop = loop;
726 if (ss->info->type == GFC_SS_SCALAR
727 || ss->info->type == GFC_SS_REFERENCE
728 || ss->info->type == GFC_SS_TEMP)
729 continue;
731 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
732 if (ss->info->data.array.subscript[n] != NULL)
733 set_ss_loop (ss->info->data.array.subscript[n], loop);
738 /* Associate a SS chain with a loop. */
740 void
741 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
743 gfc_ss *ss;
744 gfc_loopinfo *nested_loop;
746 if (head == gfc_ss_terminator)
747 return;
749 set_ss_loop (head, loop);
751 ss = head;
752 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
754 if (ss->nested_ss)
756 nested_loop = ss->nested_ss->loop;
758 /* More than one ss can belong to the same loop. Hence, we add the
759 loop to the chain only if it is different from the previously
760 added one, to avoid duplicate nested loops. */
761 if (nested_loop != loop->nested)
763 gcc_assert (nested_loop->parent == NULL);
764 nested_loop->parent = loop;
766 gcc_assert (nested_loop->next == NULL);
767 nested_loop->next = loop->nested;
768 loop->nested = nested_loop;
770 else
771 gcc_assert (nested_loop->parent == loop);
774 if (ss->next == gfc_ss_terminator)
775 ss->loop_chain = loop->ss;
776 else
777 ss->loop_chain = ss->next;
779 gcc_assert (ss == gfc_ss_terminator);
780 loop->ss = head;
784 /* Returns true if the expression is an array pointer. */
786 static bool
787 is_pointer_array (tree expr)
789 if (expr == NULL_TREE
790 || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr))
791 || GFC_CLASS_TYPE_P (TREE_TYPE (expr)))
792 return false;
794 if (TREE_CODE (expr) == VAR_DECL
795 && GFC_DECL_PTR_ARRAY_P (expr))
796 return true;
798 if (TREE_CODE (expr) == PARM_DECL
799 && GFC_DECL_PTR_ARRAY_P (expr))
800 return true;
802 if (TREE_CODE (expr) == INDIRECT_REF
803 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 0)))
804 return true;
806 /* The field declaration is marked as an pointer array. */
807 if (TREE_CODE (expr) == COMPONENT_REF
808 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 1))
809 && !GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
810 return true;
812 return false;
816 /* Return the span of an array. */
818 static tree
819 get_array_span (tree desc, gfc_expr *expr)
821 tree tmp;
823 if (is_pointer_array (desc))
824 /* This will have the span field set. */
825 tmp = gfc_conv_descriptor_span_get (desc);
826 else if (TREE_CODE (desc) == COMPONENT_REF
827 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
828 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
830 /* The descriptor is a class _data field and so use the vtable
831 size for the receiving span field. */
832 tmp = gfc_get_vptr_from_expr (desc);
833 tmp = gfc_vptr_size_get (tmp);
835 else if (expr && expr->expr_type == EXPR_VARIABLE
836 && expr->symtree->n.sym->ts.type == BT_CLASS
837 && expr->ref->type == REF_COMPONENT
838 && expr->ref->next->type == REF_ARRAY
839 && expr->ref->next->next == NULL
840 && CLASS_DATA (expr->symtree->n.sym)->attr.dimension)
842 /* Dummys come in sometimes with the descriptor detached from
843 the class field or declaration. */
844 tmp = gfc_class_vptr_get (expr->symtree->n.sym->backend_decl);
845 tmp = gfc_vptr_size_get (tmp);
847 else
849 /* If none of the fancy stuff works, the span is the element
850 size of the array. */
851 tmp = gfc_get_element_type (TREE_TYPE (desc));
852 tmp = fold_convert (gfc_array_index_type,
853 size_in_bytes (tmp));
855 return tmp;
859 /* Generate an initializer for a static pointer or allocatable array. */
861 void
862 gfc_trans_static_array_pointer (gfc_symbol * sym)
864 tree type;
866 gcc_assert (TREE_STATIC (sym->backend_decl));
867 /* Just zero the data member. */
868 type = TREE_TYPE (sym->backend_decl);
869 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
873 /* If the bounds of SE's loop have not yet been set, see if they can be
874 determined from array spec AS, which is the array spec of a called
875 function. MAPPING maps the callee's dummy arguments to the values
876 that the caller is passing. Add any initialization and finalization
877 code to SE. */
879 void
880 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
881 gfc_se * se, gfc_array_spec * as)
883 int n, dim, total_dim;
884 gfc_se tmpse;
885 gfc_ss *ss;
886 tree lower;
887 tree upper;
888 tree tmp;
890 total_dim = 0;
892 if (!as || as->type != AS_EXPLICIT)
893 return;
895 for (ss = se->ss; ss; ss = ss->parent)
897 total_dim += ss->loop->dimen;
898 for (n = 0; n < ss->loop->dimen; n++)
900 /* The bound is known, nothing to do. */
901 if (ss->loop->to[n] != NULL_TREE)
902 continue;
904 dim = ss->dim[n];
905 gcc_assert (dim < as->rank);
906 gcc_assert (ss->loop->dimen <= as->rank);
908 /* Evaluate the lower bound. */
909 gfc_init_se (&tmpse, NULL);
910 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
911 gfc_add_block_to_block (&se->pre, &tmpse.pre);
912 gfc_add_block_to_block (&se->post, &tmpse.post);
913 lower = fold_convert (gfc_array_index_type, tmpse.expr);
915 /* ...and the upper bound. */
916 gfc_init_se (&tmpse, NULL);
917 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
918 gfc_add_block_to_block (&se->pre, &tmpse.pre);
919 gfc_add_block_to_block (&se->post, &tmpse.post);
920 upper = fold_convert (gfc_array_index_type, tmpse.expr);
922 /* Set the upper bound of the loop to UPPER - LOWER. */
923 tmp = fold_build2_loc (input_location, MINUS_EXPR,
924 gfc_array_index_type, upper, lower);
925 tmp = gfc_evaluate_now (tmp, &se->pre);
926 ss->loop->to[n] = tmp;
930 gcc_assert (total_dim == as->rank);
934 /* Generate code to allocate an array temporary, or create a variable to
935 hold the data. If size is NULL, zero the descriptor so that the
936 callee will allocate the array. If DEALLOC is true, also generate code to
937 free the array afterwards.
939 If INITIAL is not NULL, it is packed using internal_pack and the result used
940 as data instead of allocating a fresh, unitialized area of memory.
942 Initialization code is added to PRE and finalization code to POST.
943 DYNAMIC is true if the caller may want to extend the array later
944 using realloc. This prevents us from putting the array on the stack. */
946 static void
947 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
948 gfc_array_info * info, tree size, tree nelem,
949 tree initial, bool dynamic, bool dealloc)
951 tree tmp;
952 tree desc;
953 bool onstack;
955 desc = info->descriptor;
956 info->offset = gfc_index_zero_node;
957 if (size == NULL_TREE || integer_zerop (size))
959 /* A callee allocated array. */
960 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
961 onstack = FALSE;
963 else
965 /* Allocate the temporary. */
966 onstack = !dynamic && initial == NULL_TREE
967 && (flag_stack_arrays
968 || gfc_can_put_var_on_stack (size));
970 if (onstack)
972 /* Make a temporary variable to hold the data. */
973 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
974 nelem, gfc_index_one_node);
975 tmp = gfc_evaluate_now (tmp, pre);
976 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
977 tmp);
978 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
979 tmp);
980 tmp = gfc_create_var (tmp, "A");
981 /* If we're here only because of -fstack-arrays we have to
982 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
983 if (!gfc_can_put_var_on_stack (size))
984 gfc_add_expr_to_block (pre,
985 fold_build1_loc (input_location,
986 DECL_EXPR, TREE_TYPE (tmp),
987 tmp));
988 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
989 gfc_conv_descriptor_data_set (pre, desc, tmp);
991 else
993 /* Allocate memory to hold the data or call internal_pack. */
994 if (initial == NULL_TREE)
996 tmp = gfc_call_malloc (pre, NULL, size);
997 tmp = gfc_evaluate_now (tmp, pre);
999 else
1001 tree packed;
1002 tree source_data;
1003 tree was_packed;
1004 stmtblock_t do_copying;
1006 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
1007 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
1008 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
1009 tmp = gfc_get_element_type (tmp);
1010 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
1011 packed = gfc_create_var (build_pointer_type (tmp), "data");
1013 tmp = build_call_expr_loc (input_location,
1014 gfor_fndecl_in_pack, 1, initial);
1015 tmp = fold_convert (TREE_TYPE (packed), tmp);
1016 gfc_add_modify (pre, packed, tmp);
1018 tmp = build_fold_indirect_ref_loc (input_location,
1019 initial);
1020 source_data = gfc_conv_descriptor_data_get (tmp);
1022 /* internal_pack may return source->data without any allocation
1023 or copying if it is already packed. If that's the case, we
1024 need to allocate and copy manually. */
1026 gfc_start_block (&do_copying);
1027 tmp = gfc_call_malloc (&do_copying, NULL, size);
1028 tmp = fold_convert (TREE_TYPE (packed), tmp);
1029 gfc_add_modify (&do_copying, packed, tmp);
1030 tmp = gfc_build_memcpy_call (packed, source_data, size);
1031 gfc_add_expr_to_block (&do_copying, tmp);
1033 was_packed = fold_build2_loc (input_location, EQ_EXPR,
1034 logical_type_node, packed,
1035 source_data);
1036 tmp = gfc_finish_block (&do_copying);
1037 tmp = build3_v (COND_EXPR, was_packed, tmp,
1038 build_empty_stmt (input_location));
1039 gfc_add_expr_to_block (pre, tmp);
1041 tmp = fold_convert (pvoid_type_node, packed);
1044 gfc_conv_descriptor_data_set (pre, desc, tmp);
1047 info->data = gfc_conv_descriptor_data_get (desc);
1049 /* The offset is zero because we create temporaries with a zero
1050 lower bound. */
1051 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
1053 if (dealloc && !onstack)
1055 /* Free the temporary. */
1056 tmp = gfc_conv_descriptor_data_get (desc);
1057 tmp = gfc_call_free (tmp);
1058 gfc_add_expr_to_block (post, tmp);
1063 /* Get the scalarizer array dimension corresponding to actual array dimension
1064 given by ARRAY_DIM.
1066 For example, if SS represents the array ref a(1,:,:,1), it is a
1067 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
1068 and 1 for ARRAY_DIM=2.
1069 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
1070 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
1071 ARRAY_DIM=3.
1072 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
1073 array. If called on the inner ss, the result would be respectively 0,1,2 for
1074 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
1075 for ARRAY_DIM=1,2. */
1077 static int
1078 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
1080 int array_ref_dim;
1081 int n;
1083 array_ref_dim = 0;
1085 for (; ss; ss = ss->parent)
1086 for (n = 0; n < ss->dimen; n++)
1087 if (ss->dim[n] < array_dim)
1088 array_ref_dim++;
1090 return array_ref_dim;
1094 static gfc_ss *
1095 innermost_ss (gfc_ss *ss)
1097 while (ss->nested_ss != NULL)
1098 ss = ss->nested_ss;
1100 return ss;
1105 /* Get the array reference dimension corresponding to the given loop dimension.
1106 It is different from the true array dimension given by the dim array in
1107 the case of a partial array reference (i.e. a(:,:,1,:) for example)
1108 It is different from the loop dimension in the case of a transposed array.
1111 static int
1112 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
1114 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
1115 ss->dim[loop_dim]);
1119 /* Generate code to create and initialize the descriptor for a temporary
1120 array. This is used for both temporaries needed by the scalarizer, and
1121 functions returning arrays. Adjusts the loop variables to be
1122 zero-based, and calculates the loop bounds for callee allocated arrays.
1123 Allocate the array unless it's callee allocated (we have a callee
1124 allocated array if 'callee_alloc' is true, or if loop->to[n] is
1125 NULL_TREE for any n). Also fills in the descriptor, data and offset
1126 fields of info if known. Returns the size of the array, or NULL for a
1127 callee allocated array.
1129 'eltype' == NULL signals that the temporary should be a class object.
1130 The 'initial' expression is used to obtain the size of the dynamic
1131 type; otherwise the allocation and initialization proceeds as for any
1132 other expression
1134 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
1135 gfc_trans_allocate_array_storage. */
1137 tree
1138 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
1139 tree eltype, tree initial, bool dynamic,
1140 bool dealloc, bool callee_alloc, locus * where)
1142 gfc_loopinfo *loop;
1143 gfc_ss *s;
1144 gfc_array_info *info;
1145 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
1146 tree type;
1147 tree desc;
1148 tree tmp;
1149 tree size;
1150 tree nelem;
1151 tree cond;
1152 tree or_expr;
1153 tree class_expr = NULL_TREE;
1154 int n, dim, tmp_dim;
1155 int total_dim = 0;
1157 /* This signals a class array for which we need the size of the
1158 dynamic type. Generate an eltype and then the class expression. */
1159 if (eltype == NULL_TREE && initial)
1161 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1162 class_expr = build_fold_indirect_ref_loc (input_location, initial);
1163 eltype = TREE_TYPE (class_expr);
1164 eltype = gfc_get_element_type (eltype);
1165 /* Obtain the structure (class) expression. */
1166 class_expr = TREE_OPERAND (class_expr, 0);
1167 gcc_assert (class_expr);
1170 memset (from, 0, sizeof (from));
1171 memset (to, 0, sizeof (to));
1173 info = &ss->info->data.array;
1175 gcc_assert (ss->dimen > 0);
1176 gcc_assert (ss->loop->dimen == ss->dimen);
1178 if (warn_array_temporaries && where)
1179 gfc_warning (OPT_Warray_temporaries,
1180 "Creating array temporary at %L", where);
1182 /* Set the lower bound to zero. */
1183 for (s = ss; s; s = s->parent)
1185 loop = s->loop;
1187 total_dim += loop->dimen;
1188 for (n = 0; n < loop->dimen; n++)
1190 dim = s->dim[n];
1192 /* Callee allocated arrays may not have a known bound yet. */
1193 if (loop->to[n])
1194 loop->to[n] = gfc_evaluate_now (
1195 fold_build2_loc (input_location, MINUS_EXPR,
1196 gfc_array_index_type,
1197 loop->to[n], loop->from[n]),
1198 pre);
1199 loop->from[n] = gfc_index_zero_node;
1201 /* We have just changed the loop bounds, we must clear the
1202 corresponding specloop, so that delta calculation is not skipped
1203 later in gfc_set_delta. */
1204 loop->specloop[n] = NULL;
1206 /* We are constructing the temporary's descriptor based on the loop
1207 dimensions. As the dimensions may be accessed in arbitrary order
1208 (think of transpose) the size taken from the n'th loop may not map
1209 to the n'th dimension of the array. We need to reconstruct loop
1210 infos in the right order before using it to set the descriptor
1211 bounds. */
1212 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1213 from[tmp_dim] = loop->from[n];
1214 to[tmp_dim] = loop->to[n];
1216 info->delta[dim] = gfc_index_zero_node;
1217 info->start[dim] = gfc_index_zero_node;
1218 info->end[dim] = gfc_index_zero_node;
1219 info->stride[dim] = gfc_index_one_node;
1223 /* Initialize the descriptor. */
1224 type =
1225 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1226 GFC_ARRAY_UNKNOWN, true);
1227 desc = gfc_create_var (type, "atmp");
1228 GFC_DECL_PACKED_ARRAY (desc) = 1;
1230 info->descriptor = desc;
1231 size = gfc_index_one_node;
1233 /* Emit a DECL_EXPR for the variable sized array type in
1234 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
1235 sizes works correctly. */
1236 tree arraytype = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (type));
1237 if (! TYPE_NAME (arraytype))
1238 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
1239 NULL_TREE, arraytype);
1240 gfc_add_expr_to_block (pre, build1 (DECL_EXPR,
1241 arraytype, TYPE_NAME (arraytype)));
1243 /* Fill in the array dtype. */
1244 tmp = gfc_conv_descriptor_dtype (desc);
1245 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1248 Fill in the bounds and stride. This is a packed array, so:
1250 size = 1;
1251 for (n = 0; n < rank; n++)
1253 stride[n] = size
1254 delta = ubound[n] + 1 - lbound[n];
1255 size = size * delta;
1257 size = size * sizeof(element);
1260 or_expr = NULL_TREE;
1262 /* If there is at least one null loop->to[n], it is a callee allocated
1263 array. */
1264 for (n = 0; n < total_dim; n++)
1265 if (to[n] == NULL_TREE)
1267 size = NULL_TREE;
1268 break;
1271 if (size == NULL_TREE)
1272 for (s = ss; s; s = s->parent)
1273 for (n = 0; n < s->loop->dimen; n++)
1275 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
1277 /* For a callee allocated array express the loop bounds in terms
1278 of the descriptor fields. */
1279 tmp = fold_build2_loc (input_location,
1280 MINUS_EXPR, gfc_array_index_type,
1281 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1282 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1283 s->loop->to[n] = tmp;
1285 else
1287 for (n = 0; n < total_dim; n++)
1289 /* Store the stride and bound components in the descriptor. */
1290 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1292 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1293 gfc_index_zero_node);
1295 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1297 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1298 gfc_array_index_type,
1299 to[n], gfc_index_one_node);
1301 /* Check whether the size for this dimension is negative. */
1302 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
1303 tmp, gfc_index_zero_node);
1304 cond = gfc_evaluate_now (cond, pre);
1306 if (n == 0)
1307 or_expr = cond;
1308 else
1309 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1310 logical_type_node, or_expr, cond);
1312 size = fold_build2_loc (input_location, MULT_EXPR,
1313 gfc_array_index_type, size, tmp);
1314 size = gfc_evaluate_now (size, pre);
1318 /* Get the size of the array. */
1319 if (size && !callee_alloc)
1321 tree elemsize;
1322 /* If or_expr is true, then the extent in at least one
1323 dimension is zero and the size is set to zero. */
1324 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1325 or_expr, gfc_index_zero_node, size);
1327 nelem = size;
1328 if (class_expr == NULL_TREE)
1329 elemsize = fold_convert (gfc_array_index_type,
1330 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1331 else
1332 elemsize = gfc_class_vtab_size_get (class_expr);
1334 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1335 size, elemsize);
1337 else
1339 nelem = size;
1340 size = NULL_TREE;
1343 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1344 dynamic, dealloc);
1346 while (ss->parent)
1347 ss = ss->parent;
1349 if (ss->dimen > ss->loop->temp_dim)
1350 ss->loop->temp_dim = ss->dimen;
1352 return size;
1356 /* Return the number of iterations in a loop that starts at START,
1357 ends at END, and has step STEP. */
1359 static tree
1360 gfc_get_iteration_count (tree start, tree end, tree step)
1362 tree tmp;
1363 tree type;
1365 type = TREE_TYPE (step);
1366 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1367 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1368 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1369 build_int_cst (type, 1));
1370 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1371 build_int_cst (type, 0));
1372 return fold_convert (gfc_array_index_type, tmp);
1376 /* Extend the data in array DESC by EXTRA elements. */
1378 static void
1379 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1381 tree arg0, arg1;
1382 tree tmp;
1383 tree size;
1384 tree ubound;
1386 if (integer_zerop (extra))
1387 return;
1389 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1391 /* Add EXTRA to the upper bound. */
1392 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1393 ubound, extra);
1394 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1396 /* Get the value of the current data pointer. */
1397 arg0 = gfc_conv_descriptor_data_get (desc);
1399 /* Calculate the new array size. */
1400 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1401 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1402 ubound, gfc_index_one_node);
1403 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1404 fold_convert (size_type_node, tmp),
1405 fold_convert (size_type_node, size));
1407 /* Call the realloc() function. */
1408 tmp = gfc_call_realloc (pblock, arg0, arg1);
1409 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1413 /* Return true if the bounds of iterator I can only be determined
1414 at run time. */
1416 static inline bool
1417 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1419 return (i->start->expr_type != EXPR_CONSTANT
1420 || i->end->expr_type != EXPR_CONSTANT
1421 || i->step->expr_type != EXPR_CONSTANT);
1425 /* Split the size of constructor element EXPR into the sum of two terms,
1426 one of which can be determined at compile time and one of which must
1427 be calculated at run time. Set *SIZE to the former and return true
1428 if the latter might be nonzero. */
1430 static bool
1431 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1433 if (expr->expr_type == EXPR_ARRAY)
1434 return gfc_get_array_constructor_size (size, expr->value.constructor);
1435 else if (expr->rank > 0)
1437 /* Calculate everything at run time. */
1438 mpz_set_ui (*size, 0);
1439 return true;
1441 else
1443 /* A single element. */
1444 mpz_set_ui (*size, 1);
1445 return false;
1450 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1451 of array constructor C. */
1453 static bool
1454 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1456 gfc_constructor *c;
1457 gfc_iterator *i;
1458 mpz_t val;
1459 mpz_t len;
1460 bool dynamic;
1462 mpz_set_ui (*size, 0);
1463 mpz_init (len);
1464 mpz_init (val);
1466 dynamic = false;
1467 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1469 i = c->iterator;
1470 if (i && gfc_iterator_has_dynamic_bounds (i))
1471 dynamic = true;
1472 else
1474 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1475 if (i)
1477 /* Multiply the static part of the element size by the
1478 number of iterations. */
1479 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1480 mpz_fdiv_q (val, val, i->step->value.integer);
1481 mpz_add_ui (val, val, 1);
1482 if (mpz_sgn (val) > 0)
1483 mpz_mul (len, len, val);
1484 else
1485 mpz_set_ui (len, 0);
1487 mpz_add (*size, *size, len);
1490 mpz_clear (len);
1491 mpz_clear (val);
1492 return dynamic;
1496 /* Make sure offset is a variable. */
1498 static void
1499 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1500 tree * offsetvar)
1502 /* We should have already created the offset variable. We cannot
1503 create it here because we may be in an inner scope. */
1504 gcc_assert (*offsetvar != NULL_TREE);
1505 gfc_add_modify (pblock, *offsetvar, *poffset);
1506 *poffset = *offsetvar;
1507 TREE_USED (*offsetvar) = 1;
1511 /* Variables needed for bounds-checking. */
1512 static bool first_len;
1513 static tree first_len_val;
1514 static bool typespec_chararray_ctor;
1516 static void
1517 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1518 tree offset, gfc_se * se, gfc_expr * expr)
1520 tree tmp;
1522 gfc_conv_expr (se, expr);
1524 /* Store the value. */
1525 tmp = build_fold_indirect_ref_loc (input_location,
1526 gfc_conv_descriptor_data_get (desc));
1527 tmp = gfc_build_array_ref (tmp, offset, NULL);
1529 if (expr->ts.type == BT_CHARACTER)
1531 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1532 tree esize;
1534 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1535 esize = fold_convert (gfc_charlen_type_node, esize);
1536 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1537 TREE_TYPE (esize), esize,
1538 build_int_cst (TREE_TYPE (esize),
1539 gfc_character_kinds[i].bit_size / 8));
1541 gfc_conv_string_parameter (se);
1542 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1544 /* The temporary is an array of pointers. */
1545 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1546 gfc_add_modify (&se->pre, tmp, se->expr);
1548 else
1550 /* The temporary is an array of string values. */
1551 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1552 /* We know the temporary and the value will be the same length,
1553 so can use memcpy. */
1554 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1555 se->string_length, se->expr, expr->ts.kind);
1557 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1559 if (first_len)
1561 gfc_add_modify (&se->pre, first_len_val,
1562 fold_convert (TREE_TYPE (first_len_val),
1563 se->string_length));
1564 first_len = false;
1566 else
1568 /* Verify that all constructor elements are of the same
1569 length. */
1570 tree rhs = fold_convert (TREE_TYPE (first_len_val),
1571 se->string_length);
1572 tree cond = fold_build2_loc (input_location, NE_EXPR,
1573 logical_type_node, first_len_val,
1574 rhs);
1575 gfc_trans_runtime_check
1576 (true, false, cond, &se->pre, &expr->where,
1577 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1578 fold_convert (long_integer_type_node, first_len_val),
1579 fold_convert (long_integer_type_node, se->string_length));
1583 else if (GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
1584 && !GFC_CLASS_TYPE_P (gfc_get_element_type (TREE_TYPE (desc))))
1586 /* Assignment of a CLASS array constructor to a derived type array. */
1587 if (expr->expr_type == EXPR_FUNCTION)
1588 se->expr = gfc_evaluate_now (se->expr, pblock);
1589 se->expr = gfc_class_data_get (se->expr);
1590 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
1591 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1592 gfc_add_modify (&se->pre, tmp, se->expr);
1594 else
1596 /* TODO: Should the frontend already have done this conversion? */
1597 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1598 gfc_add_modify (&se->pre, tmp, se->expr);
1601 gfc_add_block_to_block (pblock, &se->pre);
1602 gfc_add_block_to_block (pblock, &se->post);
1606 /* Add the contents of an array to the constructor. DYNAMIC is as for
1607 gfc_trans_array_constructor_value. */
1609 static void
1610 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1611 tree type ATTRIBUTE_UNUSED,
1612 tree desc, gfc_expr * expr,
1613 tree * poffset, tree * offsetvar,
1614 bool dynamic)
1616 gfc_se se;
1617 gfc_ss *ss;
1618 gfc_loopinfo loop;
1619 stmtblock_t body;
1620 tree tmp;
1621 tree size;
1622 int n;
1624 /* We need this to be a variable so we can increment it. */
1625 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1627 gfc_init_se (&se, NULL);
1629 /* Walk the array expression. */
1630 ss = gfc_walk_expr (expr);
1631 gcc_assert (ss != gfc_ss_terminator);
1633 /* Initialize the scalarizer. */
1634 gfc_init_loopinfo (&loop);
1635 gfc_add_ss_to_loop (&loop, ss);
1637 /* Initialize the loop. */
1638 gfc_conv_ss_startstride (&loop);
1639 gfc_conv_loop_setup (&loop, &expr->where);
1641 /* Make sure the constructed array has room for the new data. */
1642 if (dynamic)
1644 /* Set SIZE to the total number of elements in the subarray. */
1645 size = gfc_index_one_node;
1646 for (n = 0; n < loop.dimen; n++)
1648 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1649 gfc_index_one_node);
1650 size = fold_build2_loc (input_location, MULT_EXPR,
1651 gfc_array_index_type, size, tmp);
1654 /* Grow the constructed array by SIZE elements. */
1655 gfc_grow_array (&loop.pre, desc, size);
1658 /* Make the loop body. */
1659 gfc_mark_ss_chain_used (ss, 1);
1660 gfc_start_scalarized_body (&loop, &body);
1661 gfc_copy_loopinfo_to_se (&se, &loop);
1662 se.ss = ss;
1664 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1665 gcc_assert (se.ss == gfc_ss_terminator);
1667 /* Increment the offset. */
1668 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1669 *poffset, gfc_index_one_node);
1670 gfc_add_modify (&body, *poffset, tmp);
1672 /* Finish the loop. */
1673 gfc_trans_scalarizing_loops (&loop, &body);
1674 gfc_add_block_to_block (&loop.pre, &loop.post);
1675 tmp = gfc_finish_block (&loop.pre);
1676 gfc_add_expr_to_block (pblock, tmp);
1678 gfc_cleanup_loop (&loop);
1682 /* Assign the values to the elements of an array constructor. DYNAMIC
1683 is true if descriptor DESC only contains enough data for the static
1684 size calculated by gfc_get_array_constructor_size. When true, memory
1685 for the dynamic parts must be allocated using realloc. */
1687 static void
1688 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1689 tree desc, gfc_constructor_base base,
1690 tree * poffset, tree * offsetvar,
1691 bool dynamic)
1693 tree tmp;
1694 tree start = NULL_TREE;
1695 tree end = NULL_TREE;
1696 tree step = NULL_TREE;
1697 stmtblock_t body;
1698 gfc_se se;
1699 mpz_t size;
1700 gfc_constructor *c;
1702 tree shadow_loopvar = NULL_TREE;
1703 gfc_saved_var saved_loopvar;
1705 mpz_init (size);
1706 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1708 /* If this is an iterator or an array, the offset must be a variable. */
1709 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1710 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1712 /* Shadowing the iterator avoids changing its value and saves us from
1713 keeping track of it. Further, it makes sure that there's always a
1714 backend-decl for the symbol, even if there wasn't one before,
1715 e.g. in the case of an iterator that appears in a specification
1716 expression in an interface mapping. */
1717 if (c->iterator)
1719 gfc_symbol *sym;
1720 tree type;
1722 /* Evaluate loop bounds before substituting the loop variable
1723 in case they depend on it. Such a case is invalid, but it is
1724 not more expensive to do the right thing here.
1725 See PR 44354. */
1726 gfc_init_se (&se, NULL);
1727 gfc_conv_expr_val (&se, c->iterator->start);
1728 gfc_add_block_to_block (pblock, &se.pre);
1729 start = gfc_evaluate_now (se.expr, pblock);
1731 gfc_init_se (&se, NULL);
1732 gfc_conv_expr_val (&se, c->iterator->end);
1733 gfc_add_block_to_block (pblock, &se.pre);
1734 end = gfc_evaluate_now (se.expr, pblock);
1736 gfc_init_se (&se, NULL);
1737 gfc_conv_expr_val (&se, c->iterator->step);
1738 gfc_add_block_to_block (pblock, &se.pre);
1739 step = gfc_evaluate_now (se.expr, pblock);
1741 sym = c->iterator->var->symtree->n.sym;
1742 type = gfc_typenode_for_spec (&sym->ts);
1744 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1745 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1748 gfc_start_block (&body);
1750 if (c->expr->expr_type == EXPR_ARRAY)
1752 /* Array constructors can be nested. */
1753 gfc_trans_array_constructor_value (&body, type, desc,
1754 c->expr->value.constructor,
1755 poffset, offsetvar, dynamic);
1757 else if (c->expr->rank > 0)
1759 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1760 poffset, offsetvar, dynamic);
1762 else
1764 /* This code really upsets the gimplifier so don't bother for now. */
1765 gfc_constructor *p;
1766 HOST_WIDE_INT n;
1767 HOST_WIDE_INT size;
1769 p = c;
1770 n = 0;
1771 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1773 p = gfc_constructor_next (p);
1774 n++;
1776 if (n < 4)
1778 /* Scalar values. */
1779 gfc_init_se (&se, NULL);
1780 gfc_trans_array_ctor_element (&body, desc, *poffset,
1781 &se, c->expr);
1783 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1784 gfc_array_index_type,
1785 *poffset, gfc_index_one_node);
1787 else
1789 /* Collect multiple scalar constants into a constructor. */
1790 vec<constructor_elt, va_gc> *v = NULL;
1791 tree init;
1792 tree bound;
1793 tree tmptype;
1794 HOST_WIDE_INT idx = 0;
1796 p = c;
1797 /* Count the number of consecutive scalar constants. */
1798 while (p && !(p->iterator
1799 || p->expr->expr_type != EXPR_CONSTANT))
1801 gfc_init_se (&se, NULL);
1802 gfc_conv_constant (&se, p->expr);
1804 if (c->expr->ts.type != BT_CHARACTER)
1805 se.expr = fold_convert (type, se.expr);
1806 /* For constant character array constructors we build
1807 an array of pointers. */
1808 else if (POINTER_TYPE_P (type))
1809 se.expr = gfc_build_addr_expr
1810 (gfc_get_pchar_type (p->expr->ts.kind),
1811 se.expr);
1813 CONSTRUCTOR_APPEND_ELT (v,
1814 build_int_cst (gfc_array_index_type,
1815 idx++),
1816 se.expr);
1817 c = p;
1818 p = gfc_constructor_next (p);
1821 bound = size_int (n - 1);
1822 /* Create an array type to hold them. */
1823 tmptype = build_range_type (gfc_array_index_type,
1824 gfc_index_zero_node, bound);
1825 tmptype = build_array_type (type, tmptype);
1827 init = build_constructor (tmptype, v);
1828 TREE_CONSTANT (init) = 1;
1829 TREE_STATIC (init) = 1;
1830 /* Create a static variable to hold the data. */
1831 tmp = gfc_create_var (tmptype, "data");
1832 TREE_STATIC (tmp) = 1;
1833 TREE_CONSTANT (tmp) = 1;
1834 TREE_READONLY (tmp) = 1;
1835 DECL_INITIAL (tmp) = init;
1836 init = tmp;
1838 /* Use BUILTIN_MEMCPY to assign the values. */
1839 tmp = gfc_conv_descriptor_data_get (desc);
1840 tmp = build_fold_indirect_ref_loc (input_location,
1841 tmp);
1842 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1843 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1844 init = gfc_build_addr_expr (NULL_TREE, init);
1846 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1847 bound = build_int_cst (size_type_node, n * size);
1848 tmp = build_call_expr_loc (input_location,
1849 builtin_decl_explicit (BUILT_IN_MEMCPY),
1850 3, tmp, init, bound);
1851 gfc_add_expr_to_block (&body, tmp);
1853 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1854 gfc_array_index_type, *poffset,
1855 build_int_cst (gfc_array_index_type, n));
1857 if (!INTEGER_CST_P (*poffset))
1859 gfc_add_modify (&body, *offsetvar, *poffset);
1860 *poffset = *offsetvar;
1864 /* The frontend should already have done any expansions
1865 at compile-time. */
1866 if (!c->iterator)
1868 /* Pass the code as is. */
1869 tmp = gfc_finish_block (&body);
1870 gfc_add_expr_to_block (pblock, tmp);
1872 else
1874 /* Build the implied do-loop. */
1875 stmtblock_t implied_do_block;
1876 tree cond;
1877 tree exit_label;
1878 tree loopbody;
1879 tree tmp2;
1881 loopbody = gfc_finish_block (&body);
1883 /* Create a new block that holds the implied-do loop. A temporary
1884 loop-variable is used. */
1885 gfc_start_block(&implied_do_block);
1887 /* Initialize the loop. */
1888 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
1890 /* If this array expands dynamically, and the number of iterations
1891 is not constant, we won't have allocated space for the static
1892 part of C->EXPR's size. Do that now. */
1893 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1895 /* Get the number of iterations. */
1896 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1898 /* Get the static part of C->EXPR's size. */
1899 gfc_get_array_constructor_element_size (&size, c->expr);
1900 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1902 /* Grow the array by TMP * TMP2 elements. */
1903 tmp = fold_build2_loc (input_location, MULT_EXPR,
1904 gfc_array_index_type, tmp, tmp2);
1905 gfc_grow_array (&implied_do_block, desc, tmp);
1908 /* Generate the loop body. */
1909 exit_label = gfc_build_label_decl (NULL_TREE);
1910 gfc_start_block (&body);
1912 /* Generate the exit condition. Depending on the sign of
1913 the step variable we have to generate the correct
1914 comparison. */
1915 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
1916 step, build_int_cst (TREE_TYPE (step), 0));
1917 cond = fold_build3_loc (input_location, COND_EXPR,
1918 logical_type_node, tmp,
1919 fold_build2_loc (input_location, GT_EXPR,
1920 logical_type_node, shadow_loopvar, end),
1921 fold_build2_loc (input_location, LT_EXPR,
1922 logical_type_node, shadow_loopvar, end));
1923 tmp = build1_v (GOTO_EXPR, exit_label);
1924 TREE_USED (exit_label) = 1;
1925 tmp = build3_v (COND_EXPR, cond, tmp,
1926 build_empty_stmt (input_location));
1927 gfc_add_expr_to_block (&body, tmp);
1929 /* The main loop body. */
1930 gfc_add_expr_to_block (&body, loopbody);
1932 /* Increase loop variable by step. */
1933 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1934 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1935 step);
1936 gfc_add_modify (&body, shadow_loopvar, tmp);
1938 /* Finish the loop. */
1939 tmp = gfc_finish_block (&body);
1940 tmp = build1_v (LOOP_EXPR, tmp);
1941 gfc_add_expr_to_block (&implied_do_block, tmp);
1943 /* Add the exit label. */
1944 tmp = build1_v (LABEL_EXPR, exit_label);
1945 gfc_add_expr_to_block (&implied_do_block, tmp);
1947 /* Finish the implied-do loop. */
1948 tmp = gfc_finish_block(&implied_do_block);
1949 gfc_add_expr_to_block(pblock, tmp);
1951 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1954 mpz_clear (size);
1958 /* The array constructor code can create a string length with an operand
1959 in the form of a temporary variable. This variable will retain its
1960 context (current_function_decl). If we store this length tree in a
1961 gfc_charlen structure which is shared by a variable in another
1962 context, the resulting gfc_charlen structure with a variable in a
1963 different context, we could trip the assertion in expand_expr_real_1
1964 when it sees that a variable has been created in one context and
1965 referenced in another.
1967 If this might be the case, we create a new gfc_charlen structure and
1968 link it into the current namespace. */
1970 static void
1971 store_backend_decl (gfc_charlen **clp, tree len, bool force_new_cl)
1973 if (force_new_cl)
1975 gfc_charlen *new_cl = gfc_new_charlen (gfc_current_ns, *clp);
1976 *clp = new_cl;
1978 (*clp)->backend_decl = len;
1981 /* A catch-all to obtain the string length for anything that is not
1982 a substring of non-constant length, a constant, array or variable. */
1984 static void
1985 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1987 gfc_se se;
1989 /* Don't bother if we already know the length is a constant. */
1990 if (*len && INTEGER_CST_P (*len))
1991 return;
1993 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1994 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1996 /* This is easy. */
1997 gfc_conv_const_charlen (e->ts.u.cl);
1998 *len = e->ts.u.cl->backend_decl;
2000 else
2002 /* Otherwise, be brutal even if inefficient. */
2003 gfc_init_se (&se, NULL);
2005 /* No function call, in case of side effects. */
2006 se.no_function_call = 1;
2007 if (e->rank == 0)
2008 gfc_conv_expr (&se, e);
2009 else
2010 gfc_conv_expr_descriptor (&se, e);
2012 /* Fix the value. */
2013 *len = gfc_evaluate_now (se.string_length, &se.pre);
2015 gfc_add_block_to_block (block, &se.pre);
2016 gfc_add_block_to_block (block, &se.post);
2018 store_backend_decl (&e->ts.u.cl, *len, true);
2023 /* Figure out the string length of a variable reference expression.
2024 Used by get_array_ctor_strlen. */
2026 static void
2027 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
2029 gfc_ref *ref;
2030 gfc_typespec *ts;
2031 mpz_t char_len;
2033 /* Don't bother if we already know the length is a constant. */
2034 if (*len && INTEGER_CST_P (*len))
2035 return;
2037 ts = &expr->symtree->n.sym->ts;
2038 for (ref = expr->ref; ref; ref = ref->next)
2040 switch (ref->type)
2042 case REF_ARRAY:
2043 /* Array references don't change the string length. */
2044 break;
2046 case REF_COMPONENT:
2047 /* Use the length of the component. */
2048 ts = &ref->u.c.component->ts;
2049 break;
2051 case REF_SUBSTRING:
2052 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
2053 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
2055 /* Note that this might evaluate expr. */
2056 get_array_ctor_all_strlen (block, expr, len);
2057 return;
2059 mpz_init_set_ui (char_len, 1);
2060 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
2061 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
2062 *len = gfc_conv_mpz_to_tree_type (char_len, gfc_charlen_type_node);
2063 mpz_clear (char_len);
2064 return;
2066 default:
2067 gcc_unreachable ();
2071 *len = ts->u.cl->backend_decl;
2075 /* Figure out the string length of a character array constructor.
2076 If len is NULL, don't calculate the length; this happens for recursive calls
2077 when a sub-array-constructor is an element but not at the first position,
2078 so when we're not interested in the length.
2079 Returns TRUE if all elements are character constants. */
2081 bool
2082 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
2084 gfc_constructor *c;
2085 bool is_const;
2087 is_const = TRUE;
2089 if (gfc_constructor_first (base) == NULL)
2091 if (len)
2092 *len = build_int_cstu (gfc_charlen_type_node, 0);
2093 return is_const;
2096 /* Loop over all constructor elements to find out is_const, but in len we
2097 want to store the length of the first, not the last, element. We can
2098 of course exit the loop as soon as is_const is found to be false. */
2099 for (c = gfc_constructor_first (base);
2100 c && is_const; c = gfc_constructor_next (c))
2102 switch (c->expr->expr_type)
2104 case EXPR_CONSTANT:
2105 if (len && !(*len && INTEGER_CST_P (*len)))
2106 *len = build_int_cstu (gfc_charlen_type_node,
2107 c->expr->value.character.length);
2108 break;
2110 case EXPR_ARRAY:
2111 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
2112 is_const = false;
2113 break;
2115 case EXPR_VARIABLE:
2116 is_const = false;
2117 if (len)
2118 get_array_ctor_var_strlen (block, c->expr, len);
2119 break;
2121 default:
2122 is_const = false;
2123 if (len)
2124 get_array_ctor_all_strlen (block, c->expr, len);
2125 break;
2128 /* After the first iteration, we don't want the length modified. */
2129 len = NULL;
2132 return is_const;
2135 /* Check whether the array constructor C consists entirely of constant
2136 elements, and if so returns the number of those elements, otherwise
2137 return zero. Note, an empty or NULL array constructor returns zero. */
2139 unsigned HOST_WIDE_INT
2140 gfc_constant_array_constructor_p (gfc_constructor_base base)
2142 unsigned HOST_WIDE_INT nelem = 0;
2144 gfc_constructor *c = gfc_constructor_first (base);
2145 while (c)
2147 if (c->iterator
2148 || c->expr->rank > 0
2149 || c->expr->expr_type != EXPR_CONSTANT)
2150 return 0;
2151 c = gfc_constructor_next (c);
2152 nelem++;
2154 return nelem;
2158 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
2159 and the tree type of it's elements, TYPE, return a static constant
2160 variable that is compile-time initialized. */
2162 tree
2163 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
2165 tree tmptype, init, tmp;
2166 HOST_WIDE_INT nelem;
2167 gfc_constructor *c;
2168 gfc_array_spec as;
2169 gfc_se se;
2170 int i;
2171 vec<constructor_elt, va_gc> *v = NULL;
2173 /* First traverse the constructor list, converting the constants
2174 to tree to build an initializer. */
2175 nelem = 0;
2176 c = gfc_constructor_first (expr->value.constructor);
2177 while (c)
2179 gfc_init_se (&se, NULL);
2180 gfc_conv_constant (&se, c->expr);
2181 if (c->expr->ts.type != BT_CHARACTER)
2182 se.expr = fold_convert (type, se.expr);
2183 else if (POINTER_TYPE_P (type))
2184 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2185 se.expr);
2186 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2187 se.expr);
2188 c = gfc_constructor_next (c);
2189 nelem++;
2192 /* Next determine the tree type for the array. We use the gfortran
2193 front-end's gfc_get_nodesc_array_type in order to create a suitable
2194 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2196 memset (&as, 0, sizeof (gfc_array_spec));
2198 as.rank = expr->rank;
2199 as.type = AS_EXPLICIT;
2200 if (!expr->shape)
2202 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2203 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2204 NULL, nelem - 1);
2206 else
2207 for (i = 0; i < expr->rank; i++)
2209 int tmp = (int) mpz_get_si (expr->shape[i]);
2210 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2211 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2212 NULL, tmp - 1);
2215 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
2217 /* as is not needed anymore. */
2218 for (i = 0; i < as.rank + as.corank; i++)
2220 gfc_free_expr (as.lower[i]);
2221 gfc_free_expr (as.upper[i]);
2224 init = build_constructor (tmptype, v);
2226 TREE_CONSTANT (init) = 1;
2227 TREE_STATIC (init) = 1;
2229 tmp = build_decl (input_location, VAR_DECL, create_tmp_var_name ("A"),
2230 tmptype);
2231 DECL_ARTIFICIAL (tmp) = 1;
2232 DECL_IGNORED_P (tmp) = 1;
2233 TREE_STATIC (tmp) = 1;
2234 TREE_CONSTANT (tmp) = 1;
2235 TREE_READONLY (tmp) = 1;
2236 DECL_INITIAL (tmp) = init;
2237 pushdecl (tmp);
2239 return tmp;
2243 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2244 This mostly initializes the scalarizer state info structure with the
2245 appropriate values to directly use the array created by the function
2246 gfc_build_constant_array_constructor. */
2248 static void
2249 trans_constant_array_constructor (gfc_ss * ss, tree type)
2251 gfc_array_info *info;
2252 tree tmp;
2253 int i;
2255 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
2257 info = &ss->info->data.array;
2259 info->descriptor = tmp;
2260 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
2261 info->offset = gfc_index_zero_node;
2263 for (i = 0; i < ss->dimen; i++)
2265 info->delta[i] = gfc_index_zero_node;
2266 info->start[i] = gfc_index_zero_node;
2267 info->end[i] = gfc_index_zero_node;
2268 info->stride[i] = gfc_index_one_node;
2273 static int
2274 get_rank (gfc_loopinfo *loop)
2276 int rank;
2278 rank = 0;
2279 for (; loop; loop = loop->parent)
2280 rank += loop->dimen;
2282 return rank;
2286 /* Helper routine of gfc_trans_array_constructor to determine if the
2287 bounds of the loop specified by LOOP are constant and simple enough
2288 to use with trans_constant_array_constructor. Returns the
2289 iteration count of the loop if suitable, and NULL_TREE otherwise. */
2291 static tree
2292 constant_array_constructor_loop_size (gfc_loopinfo * l)
2294 gfc_loopinfo *loop;
2295 tree size = gfc_index_one_node;
2296 tree tmp;
2297 int i, total_dim;
2299 total_dim = get_rank (l);
2301 for (loop = l; loop; loop = loop->parent)
2303 for (i = 0; i < loop->dimen; i++)
2305 /* If the bounds aren't constant, return NULL_TREE. */
2306 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2307 return NULL_TREE;
2308 if (!integer_zerop (loop->from[i]))
2310 /* Only allow nonzero "from" in one-dimensional arrays. */
2311 if (total_dim != 1)
2312 return NULL_TREE;
2313 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2314 gfc_array_index_type,
2315 loop->to[i], loop->from[i]);
2317 else
2318 tmp = loop->to[i];
2319 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2320 gfc_array_index_type, tmp, gfc_index_one_node);
2321 size = fold_build2_loc (input_location, MULT_EXPR,
2322 gfc_array_index_type, size, tmp);
2326 return size;
2330 static tree *
2331 get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2333 gfc_ss *ss;
2334 int n;
2336 gcc_assert (array->nested_ss == NULL);
2338 for (ss = array; ss; ss = ss->parent)
2339 for (n = 0; n < ss->loop->dimen; n++)
2340 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2341 return &(ss->loop->to[n]);
2343 gcc_unreachable ();
2347 static gfc_loopinfo *
2348 outermost_loop (gfc_loopinfo * loop)
2350 while (loop->parent != NULL)
2351 loop = loop->parent;
2353 return loop;
2357 /* Array constructors are handled by constructing a temporary, then using that
2358 within the scalarization loop. This is not optimal, but seems by far the
2359 simplest method. */
2361 static void
2362 trans_array_constructor (gfc_ss * ss, locus * where)
2364 gfc_constructor_base c;
2365 tree offset;
2366 tree offsetvar;
2367 tree desc;
2368 tree type;
2369 tree tmp;
2370 tree *loop_ubound0;
2371 bool dynamic;
2372 bool old_first_len, old_typespec_chararray_ctor;
2373 tree old_first_len_val;
2374 gfc_loopinfo *loop, *outer_loop;
2375 gfc_ss_info *ss_info;
2376 gfc_expr *expr;
2377 gfc_ss *s;
2378 tree neg_len;
2379 char *msg;
2381 /* Save the old values for nested checking. */
2382 old_first_len = first_len;
2383 old_first_len_val = first_len_val;
2384 old_typespec_chararray_ctor = typespec_chararray_ctor;
2386 loop = ss->loop;
2387 outer_loop = outermost_loop (loop);
2388 ss_info = ss->info;
2389 expr = ss_info->expr;
2391 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2392 typespec was given for the array constructor. */
2393 typespec_chararray_ctor = (expr->ts.type == BT_CHARACTER
2394 && expr->ts.u.cl
2395 && expr->ts.u.cl->length_from_typespec);
2397 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2398 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2400 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2401 first_len = true;
2404 gcc_assert (ss->dimen == ss->loop->dimen);
2406 c = expr->value.constructor;
2407 if (expr->ts.type == BT_CHARACTER)
2409 bool const_string;
2410 bool force_new_cl = false;
2412 /* get_array_ctor_strlen walks the elements of the constructor, if a
2413 typespec was given, we already know the string length and want the one
2414 specified there. */
2415 if (typespec_chararray_ctor && expr->ts.u.cl->length
2416 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2418 gfc_se length_se;
2420 const_string = false;
2421 gfc_init_se (&length_se, NULL);
2422 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2423 gfc_charlen_type_node);
2424 ss_info->string_length = length_se.expr;
2426 /* Check if the character length is negative. If it is, then
2427 set LEN = 0. */
2428 neg_len = fold_build2_loc (input_location, LT_EXPR,
2429 logical_type_node, ss_info->string_length,
2430 build_zero_cst (TREE_TYPE
2431 (ss_info->string_length)));
2432 /* Print a warning if bounds checking is enabled. */
2433 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2435 msg = xasprintf ("Negative character length treated as LEN = 0");
2436 gfc_trans_runtime_check (false, true, neg_len, &length_se.pre,
2437 where, msg);
2438 free (msg);
2441 ss_info->string_length
2442 = fold_build3_loc (input_location, COND_EXPR,
2443 gfc_charlen_type_node, neg_len,
2444 build_zero_cst
2445 (TREE_TYPE (ss_info->string_length)),
2446 ss_info->string_length);
2447 ss_info->string_length = gfc_evaluate_now (ss_info->string_length,
2448 &length_se.pre);
2450 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2451 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2453 else
2455 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2456 &ss_info->string_length);
2457 force_new_cl = true;
2460 /* Complex character array constructors should have been taken care of
2461 and not end up here. */
2462 gcc_assert (ss_info->string_length);
2464 store_backend_decl (&expr->ts.u.cl, ss_info->string_length, force_new_cl);
2466 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2467 if (const_string)
2468 type = build_pointer_type (type);
2470 else
2471 type = gfc_typenode_for_spec (expr->ts.type == BT_CLASS
2472 ? &CLASS_DATA (expr)->ts : &expr->ts);
2474 /* See if the constructor determines the loop bounds. */
2475 dynamic = false;
2477 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2479 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
2481 /* We have a multidimensional parameter. */
2482 for (s = ss; s; s = s->parent)
2484 int n;
2485 for (n = 0; n < s->loop->dimen; n++)
2487 s->loop->from[n] = gfc_index_zero_node;
2488 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2489 gfc_index_integer_kind);
2490 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2491 gfc_array_index_type,
2492 s->loop->to[n],
2493 gfc_index_one_node);
2498 if (*loop_ubound0 == NULL_TREE)
2500 mpz_t size;
2502 /* We should have a 1-dimensional, zero-based loop. */
2503 gcc_assert (loop->parent == NULL && loop->nested == NULL);
2504 gcc_assert (loop->dimen == 1);
2505 gcc_assert (integer_zerop (loop->from[0]));
2507 /* Split the constructor size into a static part and a dynamic part.
2508 Allocate the static size up-front and record whether the dynamic
2509 size might be nonzero. */
2510 mpz_init (size);
2511 dynamic = gfc_get_array_constructor_size (&size, c);
2512 mpz_sub_ui (size, size, 1);
2513 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2514 mpz_clear (size);
2517 /* Special case constant array constructors. */
2518 if (!dynamic)
2520 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2521 if (nelem > 0)
2523 tree size = constant_array_constructor_loop_size (loop);
2524 if (size && compare_tree_int (size, nelem) == 0)
2526 trans_constant_array_constructor (ss, type);
2527 goto finish;
2532 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2533 NULL_TREE, dynamic, true, false, where);
2535 desc = ss_info->data.array.descriptor;
2536 offset = gfc_index_zero_node;
2537 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2538 TREE_NO_WARNING (offsetvar) = 1;
2539 TREE_USED (offsetvar) = 0;
2540 gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
2541 &offset, &offsetvar, dynamic);
2543 /* If the array grows dynamically, the upper bound of the loop variable
2544 is determined by the array's final upper bound. */
2545 if (dynamic)
2547 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2548 gfc_array_index_type,
2549 offsetvar, gfc_index_one_node);
2550 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2551 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2552 if (*loop_ubound0 && VAR_P (*loop_ubound0))
2553 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
2554 else
2555 *loop_ubound0 = tmp;
2558 if (TREE_USED (offsetvar))
2559 pushdecl (offsetvar);
2560 else
2561 gcc_assert (INTEGER_CST_P (offset));
2563 #if 0
2564 /* Disable bound checking for now because it's probably broken. */
2565 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2567 gcc_unreachable ();
2569 #endif
2571 finish:
2572 /* Restore old values of globals. */
2573 first_len = old_first_len;
2574 first_len_val = old_first_len_val;
2575 typespec_chararray_ctor = old_typespec_chararray_ctor;
2579 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2580 called after evaluating all of INFO's vector dimensions. Go through
2581 each such vector dimension and see if we can now fill in any missing
2582 loop bounds. */
2584 static void
2585 set_vector_loop_bounds (gfc_ss * ss)
2587 gfc_loopinfo *loop, *outer_loop;
2588 gfc_array_info *info;
2589 gfc_se se;
2590 tree tmp;
2591 tree desc;
2592 tree zero;
2593 int n;
2594 int dim;
2596 outer_loop = outermost_loop (ss->loop);
2598 info = &ss->info->data.array;
2600 for (; ss; ss = ss->parent)
2602 loop = ss->loop;
2604 for (n = 0; n < loop->dimen; n++)
2606 dim = ss->dim[n];
2607 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2608 || loop->to[n] != NULL)
2609 continue;
2611 /* Loop variable N indexes vector dimension DIM, and we don't
2612 yet know the upper bound of loop variable N. Set it to the
2613 difference between the vector's upper and lower bounds. */
2614 gcc_assert (loop->from[n] == gfc_index_zero_node);
2615 gcc_assert (info->subscript[dim]
2616 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2618 gfc_init_se (&se, NULL);
2619 desc = info->subscript[dim]->info->data.array.descriptor;
2620 zero = gfc_rank_cst[0];
2621 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2622 gfc_array_index_type,
2623 gfc_conv_descriptor_ubound_get (desc, zero),
2624 gfc_conv_descriptor_lbound_get (desc, zero));
2625 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2626 loop->to[n] = tmp;
2632 /* Tells whether a scalar argument to an elemental procedure is saved out
2633 of a scalarization loop as a value or as a reference. */
2635 bool
2636 gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info)
2638 if (ss_info->type != GFC_SS_REFERENCE)
2639 return false;
2641 /* If the actual argument can be absent (in other words, it can
2642 be a NULL reference), don't try to evaluate it; pass instead
2643 the reference directly. */
2644 if (ss_info->can_be_null_ref)
2645 return true;
2647 /* If the expression is of polymorphic type, it's actual size is not known,
2648 so we avoid copying it anywhere. */
2649 if (ss_info->data.scalar.dummy_arg
2650 && ss_info->data.scalar.dummy_arg->ts.type == BT_CLASS
2651 && ss_info->expr->ts.type == BT_CLASS)
2652 return true;
2654 /* If the expression is a data reference of aggregate type,
2655 and the data reference is not used on the left hand side,
2656 avoid a copy by saving a reference to the content. */
2657 if (!ss_info->data.scalar.needs_temporary
2658 && (ss_info->expr->ts.type == BT_DERIVED
2659 || ss_info->expr->ts.type == BT_CLASS)
2660 && gfc_expr_is_variable (ss_info->expr))
2661 return true;
2663 /* Otherwise the expression is evaluated to a temporary variable before the
2664 scalarization loop. */
2665 return false;
2669 /* Add the pre and post chains for all the scalar expressions in a SS chain
2670 to loop. This is called after the loop parameters have been calculated,
2671 but before the actual scalarizing loops. */
2673 static void
2674 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2675 locus * where)
2677 gfc_loopinfo *nested_loop, *outer_loop;
2678 gfc_se se;
2679 gfc_ss_info *ss_info;
2680 gfc_array_info *info;
2681 gfc_expr *expr;
2682 int n;
2684 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
2685 arguments could get evaluated multiple times. */
2686 if (ss->is_alloc_lhs)
2687 return;
2689 outer_loop = outermost_loop (loop);
2691 /* TODO: This can generate bad code if there are ordering dependencies,
2692 e.g., a callee allocated function and an unknown size constructor. */
2693 gcc_assert (ss != NULL);
2695 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2697 gcc_assert (ss);
2699 /* Cross loop arrays are handled from within the most nested loop. */
2700 if (ss->nested_ss != NULL)
2701 continue;
2703 ss_info = ss->info;
2704 expr = ss_info->expr;
2705 info = &ss_info->data.array;
2707 switch (ss_info->type)
2709 case GFC_SS_SCALAR:
2710 /* Scalar expression. Evaluate this now. This includes elemental
2711 dimension indices, but not array section bounds. */
2712 gfc_init_se (&se, NULL);
2713 gfc_conv_expr (&se, expr);
2714 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2716 if (expr->ts.type != BT_CHARACTER
2717 && !gfc_is_alloc_class_scalar_function (expr))
2719 /* Move the evaluation of scalar expressions outside the
2720 scalarization loop, except for WHERE assignments. */
2721 if (subscript)
2722 se.expr = convert(gfc_array_index_type, se.expr);
2723 if (!ss_info->where)
2724 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
2725 gfc_add_block_to_block (&outer_loop->pre, &se.post);
2727 else
2728 gfc_add_block_to_block (&outer_loop->post, &se.post);
2730 ss_info->data.scalar.value = se.expr;
2731 ss_info->string_length = se.string_length;
2732 break;
2734 case GFC_SS_REFERENCE:
2735 /* Scalar argument to elemental procedure. */
2736 gfc_init_se (&se, NULL);
2737 if (gfc_scalar_elemental_arg_saved_as_reference (ss_info))
2738 gfc_conv_expr_reference (&se, expr);
2739 else
2741 /* Evaluate the argument outside the loop and pass
2742 a reference to the value. */
2743 gfc_conv_expr (&se, expr);
2746 /* Ensure that a pointer to the string is stored. */
2747 if (expr->ts.type == BT_CHARACTER)
2748 gfc_conv_string_parameter (&se);
2750 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2751 gfc_add_block_to_block (&outer_loop->post, &se.post);
2752 if (gfc_is_class_scalar_expr (expr))
2753 /* This is necessary because the dynamic type will always be
2754 large than the declared type. In consequence, assigning
2755 the value to a temporary could segfault.
2756 OOP-TODO: see if this is generally correct or is the value
2757 has to be written to an allocated temporary, whose address
2758 is passed via ss_info. */
2759 ss_info->data.scalar.value = se.expr;
2760 else
2761 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
2762 &outer_loop->pre);
2764 ss_info->string_length = se.string_length;
2765 break;
2767 case GFC_SS_SECTION:
2768 /* Add the expressions for scalar and vector subscripts. */
2769 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2770 if (info->subscript[n])
2771 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2773 set_vector_loop_bounds (ss);
2774 break;
2776 case GFC_SS_VECTOR:
2777 /* Get the vector's descriptor and store it in SS. */
2778 gfc_init_se (&se, NULL);
2779 gfc_conv_expr_descriptor (&se, expr);
2780 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2781 gfc_add_block_to_block (&outer_loop->post, &se.post);
2782 info->descriptor = se.expr;
2783 break;
2785 case GFC_SS_INTRINSIC:
2786 gfc_add_intrinsic_ss_code (loop, ss);
2787 break;
2789 case GFC_SS_FUNCTION:
2790 /* Array function return value. We call the function and save its
2791 result in a temporary for use inside the loop. */
2792 gfc_init_se (&se, NULL);
2793 se.loop = loop;
2794 se.ss = ss;
2795 if (gfc_is_class_array_function (expr))
2796 expr->must_finalize = 1;
2797 gfc_conv_expr (&se, expr);
2798 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2799 gfc_add_block_to_block (&outer_loop->post, &se.post);
2800 ss_info->string_length = se.string_length;
2801 break;
2803 case GFC_SS_CONSTRUCTOR:
2804 if (expr->ts.type == BT_CHARACTER
2805 && ss_info->string_length == NULL
2806 && expr->ts.u.cl
2807 && expr->ts.u.cl->length
2808 && expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
2810 gfc_init_se (&se, NULL);
2811 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2812 gfc_charlen_type_node);
2813 ss_info->string_length = se.expr;
2814 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2815 gfc_add_block_to_block (&outer_loop->post, &se.post);
2817 trans_array_constructor (ss, where);
2818 break;
2820 case GFC_SS_TEMP:
2821 case GFC_SS_COMPONENT:
2822 /* Do nothing. These are handled elsewhere. */
2823 break;
2825 default:
2826 gcc_unreachable ();
2830 if (!subscript)
2831 for (nested_loop = loop->nested; nested_loop;
2832 nested_loop = nested_loop->next)
2833 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
2837 /* Translate expressions for the descriptor and data pointer of a SS. */
2838 /*GCC ARRAYS*/
2840 static void
2841 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2843 gfc_se se;
2844 gfc_ss_info *ss_info;
2845 gfc_array_info *info;
2846 tree tmp;
2848 ss_info = ss->info;
2849 info = &ss_info->data.array;
2851 /* Get the descriptor for the array to be scalarized. */
2852 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2853 gfc_init_se (&se, NULL);
2854 se.descriptor_only = 1;
2855 gfc_conv_expr_lhs (&se, ss_info->expr);
2856 gfc_add_block_to_block (block, &se.pre);
2857 info->descriptor = se.expr;
2858 ss_info->string_length = se.string_length;
2860 if (base)
2862 if (ss_info->expr->ts.type == BT_CHARACTER && !ss_info->expr->ts.deferred
2863 && ss_info->expr->ts.u.cl->length == NULL)
2865 /* Emit a DECL_EXPR for the variable sized array type in
2866 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
2867 sizes works correctly. */
2868 tree arraytype = TREE_TYPE (
2869 GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (info->descriptor)));
2870 if (! TYPE_NAME (arraytype))
2871 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
2872 NULL_TREE, arraytype);
2873 gfc_add_expr_to_block (block, build1 (DECL_EXPR, arraytype,
2874 TYPE_NAME (arraytype)));
2876 /* Also the data pointer. */
2877 tmp = gfc_conv_array_data (se.expr);
2878 /* If this is a variable or address of a variable we use it directly.
2879 Otherwise we must evaluate it now to avoid breaking dependency
2880 analysis by pulling the expressions for elemental array indices
2881 inside the loop. */
2882 if (!(DECL_P (tmp)
2883 || (TREE_CODE (tmp) == ADDR_EXPR
2884 && DECL_P (TREE_OPERAND (tmp, 0)))))
2885 tmp = gfc_evaluate_now (tmp, block);
2886 info->data = tmp;
2888 tmp = gfc_conv_array_offset (se.expr);
2889 info->offset = gfc_evaluate_now (tmp, block);
2891 /* Make absolutely sure that the saved_offset is indeed saved
2892 so that the variable is still accessible after the loops
2893 are translated. */
2894 info->saved_offset = info->offset;
2899 /* Initialize a gfc_loopinfo structure. */
2901 void
2902 gfc_init_loopinfo (gfc_loopinfo * loop)
2904 int n;
2906 memset (loop, 0, sizeof (gfc_loopinfo));
2907 gfc_init_block (&loop->pre);
2908 gfc_init_block (&loop->post);
2910 /* Initially scalarize in order and default to no loop reversal. */
2911 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2913 loop->order[n] = n;
2914 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2917 loop->ss = gfc_ss_terminator;
2921 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2922 chain. */
2924 void
2925 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2927 se->loop = loop;
2931 /* Return an expression for the data pointer of an array. */
2933 tree
2934 gfc_conv_array_data (tree descriptor)
2936 tree type;
2938 type = TREE_TYPE (descriptor);
2939 if (GFC_ARRAY_TYPE_P (type))
2941 if (TREE_CODE (type) == POINTER_TYPE)
2942 return descriptor;
2943 else
2945 /* Descriptorless arrays. */
2946 return gfc_build_addr_expr (NULL_TREE, descriptor);
2949 else
2950 return gfc_conv_descriptor_data_get (descriptor);
2954 /* Return an expression for the base offset of an array. */
2956 tree
2957 gfc_conv_array_offset (tree descriptor)
2959 tree type;
2961 type = TREE_TYPE (descriptor);
2962 if (GFC_ARRAY_TYPE_P (type))
2963 return GFC_TYPE_ARRAY_OFFSET (type);
2964 else
2965 return gfc_conv_descriptor_offset_get (descriptor);
2969 /* Get an expression for the array stride. */
2971 tree
2972 gfc_conv_array_stride (tree descriptor, int dim)
2974 tree tmp;
2975 tree type;
2977 type = TREE_TYPE (descriptor);
2979 /* For descriptorless arrays use the array size. */
2980 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2981 if (tmp != NULL_TREE)
2982 return tmp;
2984 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2985 return tmp;
2989 /* Like gfc_conv_array_stride, but for the lower bound. */
2991 tree
2992 gfc_conv_array_lbound (tree descriptor, int dim)
2994 tree tmp;
2995 tree type;
2997 type = TREE_TYPE (descriptor);
2999 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
3000 if (tmp != NULL_TREE)
3001 return tmp;
3003 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
3004 return tmp;
3008 /* Like gfc_conv_array_stride, but for the upper bound. */
3010 tree
3011 gfc_conv_array_ubound (tree descriptor, int dim)
3013 tree tmp;
3014 tree type;
3016 type = TREE_TYPE (descriptor);
3018 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
3019 if (tmp != NULL_TREE)
3020 return tmp;
3022 /* This should only ever happen when passing an assumed shape array
3023 as an actual parameter. The value will never be used. */
3024 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
3025 return gfc_index_zero_node;
3027 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
3028 return tmp;
3032 /* Generate code to perform an array index bound check. */
3034 static tree
3035 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
3036 locus * where, bool check_upper)
3038 tree fault;
3039 tree tmp_lo, tmp_up;
3040 tree descriptor;
3041 char *msg;
3042 const char * name = NULL;
3044 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
3045 return index;
3047 descriptor = ss->info->data.array.descriptor;
3049 index = gfc_evaluate_now (index, &se->pre);
3051 /* We find a name for the error message. */
3052 name = ss->info->expr->symtree->n.sym->name;
3053 gcc_assert (name != NULL);
3055 if (VAR_P (descriptor))
3056 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
3058 /* If upper bound is present, include both bounds in the error message. */
3059 if (check_upper)
3061 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3062 tmp_up = gfc_conv_array_ubound (descriptor, n);
3064 if (name)
3065 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3066 "outside of expected range (%%ld:%%ld)", n+1, name);
3067 else
3068 msg = xasprintf ("Index '%%ld' of dimension %d "
3069 "outside of expected range (%%ld:%%ld)", n+1);
3071 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3072 index, tmp_lo);
3073 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3074 fold_convert (long_integer_type_node, index),
3075 fold_convert (long_integer_type_node, tmp_lo),
3076 fold_convert (long_integer_type_node, tmp_up));
3077 fault = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3078 index, tmp_up);
3079 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3080 fold_convert (long_integer_type_node, index),
3081 fold_convert (long_integer_type_node, tmp_lo),
3082 fold_convert (long_integer_type_node, tmp_up));
3083 free (msg);
3085 else
3087 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3089 if (name)
3090 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3091 "below lower bound of %%ld", n+1, name);
3092 else
3093 msg = xasprintf ("Index '%%ld' of dimension %d "
3094 "below lower bound of %%ld", n+1);
3096 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3097 index, tmp_lo);
3098 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3099 fold_convert (long_integer_type_node, index),
3100 fold_convert (long_integer_type_node, tmp_lo));
3101 free (msg);
3104 return index;
3108 /* Return the offset for an index. Performs bound checking for elemental
3109 dimensions. Single element references are processed separately.
3110 DIM is the array dimension, I is the loop dimension. */
3112 static tree
3113 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
3114 gfc_array_ref * ar, tree stride)
3116 gfc_array_info *info;
3117 tree index;
3118 tree desc;
3119 tree data;
3121 info = &ss->info->data.array;
3123 /* Get the index into the array for this dimension. */
3124 if (ar)
3126 gcc_assert (ar->type != AR_ELEMENT);
3127 switch (ar->dimen_type[dim])
3129 case DIMEN_THIS_IMAGE:
3130 gcc_unreachable ();
3131 break;
3132 case DIMEN_ELEMENT:
3133 /* Elemental dimension. */
3134 gcc_assert (info->subscript[dim]
3135 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
3136 /* We've already translated this value outside the loop. */
3137 index = info->subscript[dim]->info->data.scalar.value;
3139 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3140 ar->as->type != AS_ASSUMED_SIZE
3141 || dim < ar->dimen - 1);
3142 break;
3144 case DIMEN_VECTOR:
3145 gcc_assert (info && se->loop);
3146 gcc_assert (info->subscript[dim]
3147 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
3148 desc = info->subscript[dim]->info->data.array.descriptor;
3150 /* Get a zero-based index into the vector. */
3151 index = fold_build2_loc (input_location, MINUS_EXPR,
3152 gfc_array_index_type,
3153 se->loop->loopvar[i], se->loop->from[i]);
3155 /* Multiply the index by the stride. */
3156 index = fold_build2_loc (input_location, MULT_EXPR,
3157 gfc_array_index_type,
3158 index, gfc_conv_array_stride (desc, 0));
3160 /* Read the vector to get an index into info->descriptor. */
3161 data = build_fold_indirect_ref_loc (input_location,
3162 gfc_conv_array_data (desc));
3163 index = gfc_build_array_ref (data, index, NULL);
3164 index = gfc_evaluate_now (index, &se->pre);
3165 index = fold_convert (gfc_array_index_type, index);
3167 /* Do any bounds checking on the final info->descriptor index. */
3168 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3169 ar->as->type != AS_ASSUMED_SIZE
3170 || dim < ar->dimen - 1);
3171 break;
3173 case DIMEN_RANGE:
3174 /* Scalarized dimension. */
3175 gcc_assert (info && se->loop);
3177 /* Multiply the loop variable by the stride and delta. */
3178 index = se->loop->loopvar[i];
3179 if (!integer_onep (info->stride[dim]))
3180 index = fold_build2_loc (input_location, MULT_EXPR,
3181 gfc_array_index_type, index,
3182 info->stride[dim]);
3183 if (!integer_zerop (info->delta[dim]))
3184 index = fold_build2_loc (input_location, PLUS_EXPR,
3185 gfc_array_index_type, index,
3186 info->delta[dim]);
3187 break;
3189 default:
3190 gcc_unreachable ();
3193 else
3195 /* Temporary array or derived type component. */
3196 gcc_assert (se->loop);
3197 index = se->loop->loopvar[se->loop->order[i]];
3199 /* Pointer functions can have stride[0] different from unity.
3200 Use the stride returned by the function call and stored in
3201 the descriptor for the temporary. */
3202 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
3203 && se->ss->info->expr
3204 && se->ss->info->expr->symtree
3205 && se->ss->info->expr->symtree->n.sym->result
3206 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
3207 stride = gfc_conv_descriptor_stride_get (info->descriptor,
3208 gfc_rank_cst[dim]);
3210 if (info->delta[dim] && !integer_zerop (info->delta[dim]))
3211 index = fold_build2_loc (input_location, PLUS_EXPR,
3212 gfc_array_index_type, index, info->delta[dim]);
3215 /* Multiply by the stride. */
3216 if (!integer_onep (stride))
3217 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3218 index, stride);
3220 return index;
3224 /* Build a scalarized array reference using the vptr 'size'. */
3226 static bool
3227 build_class_array_ref (gfc_se *se, tree base, tree index)
3229 tree type;
3230 tree size;
3231 tree offset;
3232 tree decl = NULL_TREE;
3233 tree tmp;
3234 gfc_expr *expr = se->ss->info->expr;
3235 gfc_ref *ref;
3236 gfc_ref *class_ref = NULL;
3237 gfc_typespec *ts;
3239 if (se->expr && DECL_P (se->expr) && DECL_LANG_SPECIFIC (se->expr)
3240 && GFC_DECL_SAVED_DESCRIPTOR (se->expr)
3241 && GFC_CLASS_TYPE_P (TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (se->expr))))
3242 decl = se->expr;
3243 else
3245 if (expr == NULL
3246 || (expr->ts.type != BT_CLASS
3247 && !gfc_is_class_array_function (expr)
3248 && !gfc_is_class_array_ref (expr, NULL)))
3249 return false;
3251 if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS)
3252 ts = &expr->symtree->n.sym->ts;
3253 else
3254 ts = NULL;
3256 for (ref = expr->ref; ref; ref = ref->next)
3258 if (ref->type == REF_COMPONENT
3259 && ref->u.c.component->ts.type == BT_CLASS
3260 && ref->next && ref->next->type == REF_COMPONENT
3261 && strcmp (ref->next->u.c.component->name, "_data") == 0
3262 && ref->next->next
3263 && ref->next->next->type == REF_ARRAY
3264 && ref->next->next->u.ar.type != AR_ELEMENT)
3266 ts = &ref->u.c.component->ts;
3267 class_ref = ref;
3268 break;
3272 if (ts == NULL)
3273 return false;
3276 if (class_ref == NULL && expr && expr->symtree->n.sym->attr.function
3277 && expr->symtree->n.sym == expr->symtree->n.sym->result
3278 && expr->symtree->n.sym->backend_decl == current_function_decl)
3280 decl = gfc_get_fake_result_decl (expr->symtree->n.sym, 0);
3282 else if (expr && gfc_is_class_array_function (expr))
3284 size = NULL_TREE;
3285 decl = NULL_TREE;
3286 for (tmp = base; tmp; tmp = TREE_OPERAND (tmp, 0))
3288 tree type;
3289 type = TREE_TYPE (tmp);
3290 while (type)
3292 if (GFC_CLASS_TYPE_P (type))
3293 decl = tmp;
3294 if (type != TYPE_CANONICAL (type))
3295 type = TYPE_CANONICAL (type);
3296 else
3297 type = NULL_TREE;
3299 if (VAR_P (tmp))
3300 break;
3303 if (decl == NULL_TREE)
3304 return false;
3306 se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
3308 else if (class_ref == NULL)
3310 if (decl == NULL_TREE)
3311 decl = expr->symtree->n.sym->backend_decl;
3312 /* For class arrays the tree containing the class is stored in
3313 GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl.
3314 For all others it's sym's backend_decl directly. */
3315 if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
3316 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
3318 else
3320 /* Remove everything after the last class reference, convert the
3321 expression and then recover its tailend once more. */
3322 gfc_se tmpse;
3323 ref = class_ref->next;
3324 class_ref->next = NULL;
3325 gfc_init_se (&tmpse, NULL);
3326 gfc_conv_expr (&tmpse, expr);
3327 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3328 decl = tmpse.expr;
3329 class_ref->next = ref;
3332 if (POINTER_TYPE_P (TREE_TYPE (decl)))
3333 decl = build_fold_indirect_ref_loc (input_location, decl);
3335 if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
3336 return false;
3338 size = gfc_class_vtab_size_get (decl);
3340 /* For unlimited polymorphic entities then _len component needs to be
3341 multiplied with the size. If no _len component is present, then
3342 gfc_class_len_or_zero_get () return a zero_node. */
3343 tmp = gfc_class_len_or_zero_get (decl);
3344 if (!integer_zerop (tmp))
3345 size = fold_build2 (MULT_EXPR, TREE_TYPE (index),
3346 fold_convert (TREE_TYPE (index), size),
3347 fold_build2 (MAX_EXPR, TREE_TYPE (index),
3348 fold_convert (TREE_TYPE (index), tmp),
3349 fold_convert (TREE_TYPE (index),
3350 integer_one_node)));
3351 else
3352 size = fold_convert (TREE_TYPE (index), size);
3354 /* Build the address of the element. */
3355 type = TREE_TYPE (TREE_TYPE (base));
3356 offset = fold_build2_loc (input_location, MULT_EXPR,
3357 gfc_array_index_type,
3358 index, size);
3359 tmp = gfc_build_addr_expr (pvoid_type_node, base);
3360 tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
3361 tmp = fold_convert (build_pointer_type (type), tmp);
3363 /* Return the element in the se expression. */
3364 se->expr = build_fold_indirect_ref_loc (input_location, tmp);
3365 return true;
3369 /* Build a scalarized reference to an array. */
3371 static void
3372 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
3374 gfc_array_info *info;
3375 tree decl = NULL_TREE;
3376 tree index;
3377 tree tmp;
3378 gfc_ss *ss;
3379 gfc_expr *expr;
3380 int n;
3382 ss = se->ss;
3383 expr = ss->info->expr;
3384 info = &ss->info->data.array;
3385 if (ar)
3386 n = se->loop->order[0];
3387 else
3388 n = 0;
3390 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
3391 /* Add the offset for this dimension to the stored offset for all other
3392 dimensions. */
3393 if (info->offset && !integer_zerop (info->offset))
3394 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3395 index, info->offset);
3397 if (expr && ((is_subref_array (expr)
3398 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor)))
3399 || (expr->ts.deferred && (expr->expr_type == EXPR_VARIABLE
3400 || expr->expr_type == EXPR_FUNCTION))))
3401 decl = expr->symtree->n.sym->backend_decl;
3403 /* A pointer array component can be detected from its field decl. Fix
3404 the descriptor, mark the resulting variable decl and pass it to
3405 gfc_build_array_ref. */
3406 if (is_pointer_array (info->descriptor))
3408 if (TREE_CODE (info->descriptor) == COMPONENT_REF)
3410 decl = gfc_evaluate_now (info->descriptor, &se->pre);
3411 GFC_DECL_PTR_ARRAY_P (decl) = 1;
3412 TREE_USED (decl) = 1;
3414 else if (TREE_CODE (info->descriptor) == INDIRECT_REF)
3415 decl = TREE_OPERAND (info->descriptor, 0);
3417 if (decl == NULL_TREE)
3418 decl = info->descriptor;
3421 tmp = build_fold_indirect_ref_loc (input_location, info->data);
3423 /* Use the vptr 'size' field to access a class the element of a class
3424 array. */
3425 if (build_class_array_ref (se, tmp, index))
3426 return;
3428 se->expr = gfc_build_array_ref (tmp, index, decl);
3432 /* Translate access of temporary array. */
3434 void
3435 gfc_conv_tmp_array_ref (gfc_se * se)
3437 se->string_length = se->ss->info->string_length;
3438 gfc_conv_scalarized_array_ref (se, NULL);
3439 gfc_advance_se_ss_chain (se);
3442 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3444 static void
3445 add_to_offset (tree *cst_offset, tree *offset, tree t)
3447 if (TREE_CODE (t) == INTEGER_CST)
3448 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3449 else
3451 if (!integer_zerop (*offset))
3452 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3453 gfc_array_index_type, *offset, t);
3454 else
3455 *offset = t;
3460 static tree
3461 build_array_ref (tree desc, tree offset, tree decl, tree vptr)
3463 tree tmp;
3464 tree type;
3465 tree cdesc;
3467 /* For class arrays the class declaration is stored in the saved
3468 descriptor. */
3469 if (INDIRECT_REF_P (desc)
3470 && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
3471 && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
3472 cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
3473 TREE_OPERAND (desc, 0)));
3474 else
3475 cdesc = desc;
3477 /* Class container types do not always have the GFC_CLASS_TYPE_P
3478 but the canonical type does. */
3479 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
3480 && TREE_CODE (cdesc) == COMPONENT_REF)
3482 type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
3483 if (TYPE_CANONICAL (type)
3484 && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
3485 vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
3488 tmp = gfc_conv_array_data (desc);
3489 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3490 tmp = gfc_build_array_ref (tmp, offset, decl, vptr);
3491 return tmp;
3495 /* Build an array reference. se->expr already holds the array descriptor.
3496 This should be either a variable, indirect variable reference or component
3497 reference. For arrays which do not have a descriptor, se->expr will be
3498 the data pointer.
3499 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3501 void
3502 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
3503 locus * where)
3505 int n;
3506 tree offset, cst_offset;
3507 tree tmp;
3508 tree stride;
3509 tree decl = NULL_TREE;
3510 gfc_se indexse;
3511 gfc_se tmpse;
3512 gfc_symbol * sym = expr->symtree->n.sym;
3513 char *var_name = NULL;
3515 if (ar->dimen == 0)
3517 gcc_assert (ar->codimen);
3519 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3520 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
3521 else
3523 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
3524 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
3525 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
3527 /* Use the actual tree type and not the wrapped coarray. */
3528 if (!se->want_pointer)
3529 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
3530 se->expr);
3533 return;
3536 /* Handle scalarized references separately. */
3537 if (ar->type != AR_ELEMENT)
3539 gfc_conv_scalarized_array_ref (se, ar);
3540 gfc_advance_se_ss_chain (se);
3541 return;
3544 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3546 size_t len;
3547 gfc_ref *ref;
3549 len = strlen (sym->name) + 1;
3550 for (ref = expr->ref; ref; ref = ref->next)
3552 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3553 break;
3554 if (ref->type == REF_COMPONENT)
3555 len += 2 + strlen (ref->u.c.component->name);
3558 var_name = XALLOCAVEC (char, len);
3559 strcpy (var_name, sym->name);
3561 for (ref = expr->ref; ref; ref = ref->next)
3563 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3564 break;
3565 if (ref->type == REF_COMPONENT)
3567 strcat (var_name, "%%");
3568 strcat (var_name, ref->u.c.component->name);
3573 cst_offset = offset = gfc_index_zero_node;
3574 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
3576 /* Calculate the offsets from all the dimensions. Make sure to associate
3577 the final offset so that we form a chain of loop invariant summands. */
3578 for (n = ar->dimen - 1; n >= 0; n--)
3580 /* Calculate the index for this dimension. */
3581 gfc_init_se (&indexse, se);
3582 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
3583 gfc_add_block_to_block (&se->pre, &indexse.pre);
3585 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3587 /* Check array bounds. */
3588 tree cond;
3589 char *msg;
3591 /* Evaluate the indexse.expr only once. */
3592 indexse.expr = save_expr (indexse.expr);
3594 /* Lower bound. */
3595 tmp = gfc_conv_array_lbound (se->expr, n);
3596 if (sym->attr.temporary)
3598 gfc_init_se (&tmpse, se);
3599 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
3600 gfc_array_index_type);
3601 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3602 tmp = tmpse.expr;
3605 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3606 indexse.expr, tmp);
3607 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3608 "below lower bound of %%ld", n+1, var_name);
3609 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3610 fold_convert (long_integer_type_node,
3611 indexse.expr),
3612 fold_convert (long_integer_type_node, tmp));
3613 free (msg);
3615 /* Upper bound, but not for the last dimension of assumed-size
3616 arrays. */
3617 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
3619 tmp = gfc_conv_array_ubound (se->expr, n);
3620 if (sym->attr.temporary)
3622 gfc_init_se (&tmpse, se);
3623 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
3624 gfc_array_index_type);
3625 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3626 tmp = tmpse.expr;
3629 cond = fold_build2_loc (input_location, GT_EXPR,
3630 logical_type_node, indexse.expr, tmp);
3631 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3632 "above upper bound of %%ld", n+1, var_name);
3633 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3634 fold_convert (long_integer_type_node,
3635 indexse.expr),
3636 fold_convert (long_integer_type_node, tmp));
3637 free (msg);
3641 /* Multiply the index by the stride. */
3642 stride = gfc_conv_array_stride (se->expr, n);
3643 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3644 indexse.expr, stride);
3646 /* And add it to the total. */
3647 add_to_offset (&cst_offset, &offset, tmp);
3650 if (!integer_zerop (cst_offset))
3651 offset = fold_build2_loc (input_location, PLUS_EXPR,
3652 gfc_array_index_type, offset, cst_offset);
3654 /* A pointer array component can be detected from its field decl. Fix
3655 the descriptor, mark the resulting variable decl and pass it to
3656 build_array_ref. */
3657 if (!expr->ts.deferred && !sym->attr.codimension
3658 && is_pointer_array (se->expr))
3660 if (TREE_CODE (se->expr) == COMPONENT_REF)
3662 decl = gfc_evaluate_now (se->expr, &se->pre);
3663 GFC_DECL_PTR_ARRAY_P (decl) = 1;
3664 TREE_USED (decl) = 1;
3666 else if (TREE_CODE (se->expr) == INDIRECT_REF)
3667 decl = TREE_OPERAND (se->expr, 0);
3668 else
3669 decl = se->expr;
3671 else if (expr->ts.deferred
3672 || (sym->ts.type == BT_CHARACTER
3673 && sym->attr.select_type_temporary))
3674 decl = sym->backend_decl;
3675 else if (sym->ts.type == BT_CLASS)
3676 decl = NULL_TREE;
3678 se->expr = build_array_ref (se->expr, offset, decl, se->class_vptr);
3682 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
3683 LOOP_DIM dimension (if any) to array's offset. */
3685 static void
3686 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
3687 gfc_array_ref *ar, int array_dim, int loop_dim)
3689 gfc_se se;
3690 gfc_array_info *info;
3691 tree stride, index;
3693 info = &ss->info->data.array;
3695 gfc_init_se (&se, NULL);
3696 se.loop = loop;
3697 se.expr = info->descriptor;
3698 stride = gfc_conv_array_stride (info->descriptor, array_dim);
3699 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
3700 gfc_add_block_to_block (pblock, &se.pre);
3702 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
3703 gfc_array_index_type,
3704 info->offset, index);
3705 info->offset = gfc_evaluate_now (info->offset, pblock);
3709 /* Generate the code to be executed immediately before entering a
3710 scalarization loop. */
3712 static void
3713 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
3714 stmtblock_t * pblock)
3716 tree stride;
3717 gfc_ss_info *ss_info;
3718 gfc_array_info *info;
3719 gfc_ss_type ss_type;
3720 gfc_ss *ss, *pss;
3721 gfc_loopinfo *ploop;
3722 gfc_array_ref *ar;
3723 int i;
3725 /* This code will be executed before entering the scalarization loop
3726 for this dimension. */
3727 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3729 ss_info = ss->info;
3731 if ((ss_info->useflags & flag) == 0)
3732 continue;
3734 ss_type = ss_info->type;
3735 if (ss_type != GFC_SS_SECTION
3736 && ss_type != GFC_SS_FUNCTION
3737 && ss_type != GFC_SS_CONSTRUCTOR
3738 && ss_type != GFC_SS_COMPONENT)
3739 continue;
3741 info = &ss_info->data.array;
3743 gcc_assert (dim < ss->dimen);
3744 gcc_assert (ss->dimen == loop->dimen);
3746 if (info->ref)
3747 ar = &info->ref->u.ar;
3748 else
3749 ar = NULL;
3751 if (dim == loop->dimen - 1 && loop->parent != NULL)
3753 /* If we are in the outermost dimension of this loop, the previous
3754 dimension shall be in the parent loop. */
3755 gcc_assert (ss->parent != NULL);
3757 pss = ss->parent;
3758 ploop = loop->parent;
3760 /* ss and ss->parent are about the same array. */
3761 gcc_assert (ss_info == pss->info);
3763 else
3765 ploop = loop;
3766 pss = ss;
3769 if (dim == loop->dimen - 1)
3770 i = 0;
3771 else
3772 i = dim + 1;
3774 /* For the time being, there is no loop reordering. */
3775 gcc_assert (i == ploop->order[i]);
3776 i = ploop->order[i];
3778 if (dim == loop->dimen - 1 && loop->parent == NULL)
3780 stride = gfc_conv_array_stride (info->descriptor,
3781 innermost_ss (ss)->dim[i]);
3783 /* Calculate the stride of the innermost loop. Hopefully this will
3784 allow the backend optimizers to do their stuff more effectively.
3786 info->stride0 = gfc_evaluate_now (stride, pblock);
3788 /* For the outermost loop calculate the offset due to any
3789 elemental dimensions. It will have been initialized with the
3790 base offset of the array. */
3791 if (info->ref)
3793 for (i = 0; i < ar->dimen; i++)
3795 if (ar->dimen_type[i] != DIMEN_ELEMENT)
3796 continue;
3798 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
3802 else
3803 /* Add the offset for the previous loop dimension. */
3804 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
3806 /* Remember this offset for the second loop. */
3807 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
3808 info->saved_offset = info->offset;
3813 /* Start a scalarized expression. Creates a scope and declares loop
3814 variables. */
3816 void
3817 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
3819 int dim;
3820 int n;
3821 int flags;
3823 gcc_assert (!loop->array_parameter);
3825 for (dim = loop->dimen - 1; dim >= 0; dim--)
3827 n = loop->order[dim];
3829 gfc_start_block (&loop->code[n]);
3831 /* Create the loop variable. */
3832 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
3834 if (dim < loop->temp_dim)
3835 flags = 3;
3836 else
3837 flags = 1;
3838 /* Calculate values that will be constant within this loop. */
3839 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3841 gfc_start_block (pbody);
3845 /* Generates the actual loop code for a scalarization loop. */
3847 void
3848 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3849 stmtblock_t * pbody)
3851 stmtblock_t block;
3852 tree cond;
3853 tree tmp;
3854 tree loopbody;
3855 tree exit_label;
3856 tree stmt;
3857 tree init;
3858 tree incr;
3860 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS
3861 | OMPWS_SCALARIZER_BODY))
3862 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3863 && n == loop->dimen - 1)
3865 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3866 init = make_tree_vec (1);
3867 cond = make_tree_vec (1);
3868 incr = make_tree_vec (1);
3870 /* Cycle statement is implemented with a goto. Exit statement must not
3871 be present for this loop. */
3872 exit_label = gfc_build_label_decl (NULL_TREE);
3873 TREE_USED (exit_label) = 1;
3875 /* Label for cycle statements (if needed). */
3876 tmp = build1_v (LABEL_EXPR, exit_label);
3877 gfc_add_expr_to_block (pbody, tmp);
3879 stmt = make_node (OMP_FOR);
3881 TREE_TYPE (stmt) = void_type_node;
3882 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3884 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3885 OMP_CLAUSE_SCHEDULE);
3886 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3887 = OMP_CLAUSE_SCHEDULE_STATIC;
3888 if (ompws_flags & OMPWS_NOWAIT)
3889 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3890 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3892 /* Initialize the loopvar. */
3893 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3894 loop->from[n]);
3895 OMP_FOR_INIT (stmt) = init;
3896 /* The exit condition. */
3897 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3898 logical_type_node,
3899 loop->loopvar[n], loop->to[n]);
3900 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3901 OMP_FOR_COND (stmt) = cond;
3902 /* Increment the loopvar. */
3903 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3904 loop->loopvar[n], gfc_index_one_node);
3905 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3906 void_type_node, loop->loopvar[n], tmp);
3907 OMP_FOR_INCR (stmt) = incr;
3909 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3910 gfc_add_expr_to_block (&loop->code[n], stmt);
3912 else
3914 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3915 && (loop->temp_ss == NULL);
3917 loopbody = gfc_finish_block (pbody);
3919 if (reverse_loop)
3920 std::swap (loop->from[n], loop->to[n]);
3922 /* Initialize the loopvar. */
3923 if (loop->loopvar[n] != loop->from[n])
3924 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3926 exit_label = gfc_build_label_decl (NULL_TREE);
3928 /* Generate the loop body. */
3929 gfc_init_block (&block);
3931 /* The exit condition. */
3932 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3933 logical_type_node, loop->loopvar[n], loop->to[n]);
3934 tmp = build1_v (GOTO_EXPR, exit_label);
3935 TREE_USED (exit_label) = 1;
3936 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3937 gfc_add_expr_to_block (&block, tmp);
3939 /* The main body. */
3940 gfc_add_expr_to_block (&block, loopbody);
3942 /* Increment the loopvar. */
3943 tmp = fold_build2_loc (input_location,
3944 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3945 gfc_array_index_type, loop->loopvar[n],
3946 gfc_index_one_node);
3948 gfc_add_modify (&block, loop->loopvar[n], tmp);
3950 /* Build the loop. */
3951 tmp = gfc_finish_block (&block);
3952 tmp = build1_v (LOOP_EXPR, tmp);
3953 gfc_add_expr_to_block (&loop->code[n], tmp);
3955 /* Add the exit label. */
3956 tmp = build1_v (LABEL_EXPR, exit_label);
3957 gfc_add_expr_to_block (&loop->code[n], tmp);
3963 /* Finishes and generates the loops for a scalarized expression. */
3965 void
3966 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3968 int dim;
3969 int n;
3970 gfc_ss *ss;
3971 stmtblock_t *pblock;
3972 tree tmp;
3974 pblock = body;
3975 /* Generate the loops. */
3976 for (dim = 0; dim < loop->dimen; dim++)
3978 n = loop->order[dim];
3979 gfc_trans_scalarized_loop_end (loop, n, pblock);
3980 loop->loopvar[n] = NULL_TREE;
3981 pblock = &loop->code[n];
3984 tmp = gfc_finish_block (pblock);
3985 gfc_add_expr_to_block (&loop->pre, tmp);
3987 /* Clear all the used flags. */
3988 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3989 if (ss->parent == NULL)
3990 ss->info->useflags = 0;
3994 /* Finish the main body of a scalarized expression, and start the secondary
3995 copying body. */
3997 void
3998 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
4000 int dim;
4001 int n;
4002 stmtblock_t *pblock;
4003 gfc_ss *ss;
4005 pblock = body;
4006 /* We finish as many loops as are used by the temporary. */
4007 for (dim = 0; dim < loop->temp_dim - 1; dim++)
4009 n = loop->order[dim];
4010 gfc_trans_scalarized_loop_end (loop, n, pblock);
4011 loop->loopvar[n] = NULL_TREE;
4012 pblock = &loop->code[n];
4015 /* We don't want to finish the outermost loop entirely. */
4016 n = loop->order[loop->temp_dim - 1];
4017 gfc_trans_scalarized_loop_end (loop, n, pblock);
4019 /* Restore the initial offsets. */
4020 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4022 gfc_ss_type ss_type;
4023 gfc_ss_info *ss_info;
4025 ss_info = ss->info;
4027 if ((ss_info->useflags & 2) == 0)
4028 continue;
4030 ss_type = ss_info->type;
4031 if (ss_type != GFC_SS_SECTION
4032 && ss_type != GFC_SS_FUNCTION
4033 && ss_type != GFC_SS_CONSTRUCTOR
4034 && ss_type != GFC_SS_COMPONENT)
4035 continue;
4037 ss_info->data.array.offset = ss_info->data.array.saved_offset;
4040 /* Restart all the inner loops we just finished. */
4041 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
4043 n = loop->order[dim];
4045 gfc_start_block (&loop->code[n]);
4047 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
4049 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
4052 /* Start a block for the secondary copying code. */
4053 gfc_start_block (body);
4057 /* Precalculate (either lower or upper) bound of an array section.
4058 BLOCK: Block in which the (pre)calculation code will go.
4059 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
4060 VALUES[DIM]: Specified bound (NULL <=> unspecified).
4061 DESC: Array descriptor from which the bound will be picked if unspecified
4062 (either lower or upper bound according to LBOUND). */
4064 static void
4065 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
4066 tree desc, int dim, bool lbound, bool deferred)
4068 gfc_se se;
4069 gfc_expr * input_val = values[dim];
4070 tree *output = &bounds[dim];
4073 if (input_val)
4075 /* Specified section bound. */
4076 gfc_init_se (&se, NULL);
4077 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
4078 gfc_add_block_to_block (block, &se.pre);
4079 *output = se.expr;
4081 else if (deferred && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
4083 /* The gfc_conv_array_lbound () routine returns a constant zero for
4084 deferred length arrays, which in the scalarizer wreaks havoc, when
4085 copying to a (newly allocated) one-based array.
4086 Keep returning the actual result in sync for both bounds. */
4087 *output = lbound ? gfc_conv_descriptor_lbound_get (desc,
4088 gfc_rank_cst[dim]):
4089 gfc_conv_descriptor_ubound_get (desc,
4090 gfc_rank_cst[dim]);
4092 else
4094 /* No specific bound specified so use the bound of the array. */
4095 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
4096 gfc_conv_array_ubound (desc, dim);
4098 *output = gfc_evaluate_now (*output, block);
4102 /* Calculate the lower bound of an array section. */
4104 static void
4105 gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
4107 gfc_expr *stride = NULL;
4108 tree desc;
4109 gfc_se se;
4110 gfc_array_info *info;
4111 gfc_array_ref *ar;
4113 gcc_assert (ss->info->type == GFC_SS_SECTION);
4115 info = &ss->info->data.array;
4116 ar = &info->ref->u.ar;
4118 if (ar->dimen_type[dim] == DIMEN_VECTOR)
4120 /* We use a zero-based index to access the vector. */
4121 info->start[dim] = gfc_index_zero_node;
4122 info->end[dim] = NULL;
4123 info->stride[dim] = gfc_index_one_node;
4124 return;
4127 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
4128 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
4129 desc = info->descriptor;
4130 stride = ar->stride[dim];
4133 /* Calculate the start of the range. For vector subscripts this will
4134 be the range of the vector. */
4135 evaluate_bound (block, info->start, ar->start, desc, dim, true,
4136 ar->as->type == AS_DEFERRED);
4138 /* Similarly calculate the end. Although this is not used in the
4139 scalarizer, it is needed when checking bounds and where the end
4140 is an expression with side-effects. */
4141 evaluate_bound (block, info->end, ar->end, desc, dim, false,
4142 ar->as->type == AS_DEFERRED);
4145 /* Calculate the stride. */
4146 if (stride == NULL)
4147 info->stride[dim] = gfc_index_one_node;
4148 else
4150 gfc_init_se (&se, NULL);
4151 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
4152 gfc_add_block_to_block (block, &se.pre);
4153 info->stride[dim] = gfc_evaluate_now (se.expr, block);
4158 /* Calculates the range start and stride for a SS chain. Also gets the
4159 descriptor and data pointer. The range of vector subscripts is the size
4160 of the vector. Array bounds are also checked. */
4162 void
4163 gfc_conv_ss_startstride (gfc_loopinfo * loop)
4165 int n;
4166 tree tmp;
4167 gfc_ss *ss;
4168 tree desc;
4170 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4172 loop->dimen = 0;
4173 /* Determine the rank of the loop. */
4174 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4176 switch (ss->info->type)
4178 case GFC_SS_SECTION:
4179 case GFC_SS_CONSTRUCTOR:
4180 case GFC_SS_FUNCTION:
4181 case GFC_SS_COMPONENT:
4182 loop->dimen = ss->dimen;
4183 goto done;
4185 /* As usual, lbound and ubound are exceptions!. */
4186 case GFC_SS_INTRINSIC:
4187 switch (ss->info->expr->value.function.isym->id)
4189 case GFC_ISYM_LBOUND:
4190 case GFC_ISYM_UBOUND:
4191 case GFC_ISYM_LCOBOUND:
4192 case GFC_ISYM_UCOBOUND:
4193 case GFC_ISYM_THIS_IMAGE:
4194 loop->dimen = ss->dimen;
4195 goto done;
4197 default:
4198 break;
4201 default:
4202 break;
4206 /* We should have determined the rank of the expression by now. If
4207 not, that's bad news. */
4208 gcc_unreachable ();
4210 done:
4211 /* Loop over all the SS in the chain. */
4212 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4214 gfc_ss_info *ss_info;
4215 gfc_array_info *info;
4216 gfc_expr *expr;
4218 ss_info = ss->info;
4219 expr = ss_info->expr;
4220 info = &ss_info->data.array;
4222 if (expr && expr->shape && !info->shape)
4223 info->shape = expr->shape;
4225 switch (ss_info->type)
4227 case GFC_SS_SECTION:
4228 /* Get the descriptor for the array. If it is a cross loops array,
4229 we got the descriptor already in the outermost loop. */
4230 if (ss->parent == NULL)
4231 gfc_conv_ss_descriptor (&outer_loop->pre, ss,
4232 !loop->array_parameter);
4234 for (n = 0; n < ss->dimen; n++)
4235 gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
4236 break;
4238 case GFC_SS_INTRINSIC:
4239 switch (expr->value.function.isym->id)
4241 /* Fall through to supply start and stride. */
4242 case GFC_ISYM_LBOUND:
4243 case GFC_ISYM_UBOUND:
4245 gfc_expr *arg;
4247 /* This is the variant without DIM=... */
4248 gcc_assert (expr->value.function.actual->next->expr == NULL);
4250 arg = expr->value.function.actual->expr;
4251 if (arg->rank == -1)
4253 gfc_se se;
4254 tree rank, tmp;
4256 /* The rank (hence the return value's shape) is unknown,
4257 we have to retrieve it. */
4258 gfc_init_se (&se, NULL);
4259 se.descriptor_only = 1;
4260 gfc_conv_expr (&se, arg);
4261 /* This is a bare variable, so there is no preliminary
4262 or cleanup code. */
4263 gcc_assert (se.pre.head == NULL_TREE
4264 && se.post.head == NULL_TREE);
4265 rank = gfc_conv_descriptor_rank (se.expr);
4266 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4267 gfc_array_index_type,
4268 fold_convert (gfc_array_index_type,
4269 rank),
4270 gfc_index_one_node);
4271 info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
4272 info->start[0] = gfc_index_zero_node;
4273 info->stride[0] = gfc_index_one_node;
4274 continue;
4276 /* Otherwise fall through GFC_SS_FUNCTION. */
4277 gcc_fallthrough ();
4279 case GFC_ISYM_LCOBOUND:
4280 case GFC_ISYM_UCOBOUND:
4281 case GFC_ISYM_THIS_IMAGE:
4282 break;
4284 default:
4285 continue;
4288 /* FALLTHRU */
4289 case GFC_SS_CONSTRUCTOR:
4290 case GFC_SS_FUNCTION:
4291 for (n = 0; n < ss->dimen; n++)
4293 int dim = ss->dim[n];
4295 info->start[dim] = gfc_index_zero_node;
4296 info->end[dim] = gfc_index_zero_node;
4297 info->stride[dim] = gfc_index_one_node;
4299 break;
4301 default:
4302 break;
4306 /* The rest is just runtime bound checking. */
4307 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4309 stmtblock_t block;
4310 tree lbound, ubound;
4311 tree end;
4312 tree size[GFC_MAX_DIMENSIONS];
4313 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
4314 gfc_array_info *info;
4315 char *msg;
4316 int dim;
4318 gfc_start_block (&block);
4320 for (n = 0; n < loop->dimen; n++)
4321 size[n] = NULL_TREE;
4323 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4325 stmtblock_t inner;
4326 gfc_ss_info *ss_info;
4327 gfc_expr *expr;
4328 locus *expr_loc;
4329 const char *expr_name;
4331 ss_info = ss->info;
4332 if (ss_info->type != GFC_SS_SECTION)
4333 continue;
4335 /* Catch allocatable lhs in f2003. */
4336 if (flag_realloc_lhs && ss->is_alloc_lhs)
4337 continue;
4339 expr = ss_info->expr;
4340 expr_loc = &expr->where;
4341 expr_name = expr->symtree->name;
4343 gfc_start_block (&inner);
4345 /* TODO: range checking for mapped dimensions. */
4346 info = &ss_info->data.array;
4348 /* This code only checks ranges. Elemental and vector
4349 dimensions are checked later. */
4350 for (n = 0; n < loop->dimen; n++)
4352 bool check_upper;
4354 dim = ss->dim[n];
4355 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
4356 continue;
4358 if (dim == info->ref->u.ar.dimen - 1
4359 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
4360 check_upper = false;
4361 else
4362 check_upper = true;
4364 /* Zero stride is not allowed. */
4365 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
4366 info->stride[dim], gfc_index_zero_node);
4367 msg = xasprintf ("Zero stride is not allowed, for dimension %d "
4368 "of array '%s'", dim + 1, expr_name);
4369 gfc_trans_runtime_check (true, false, tmp, &inner,
4370 expr_loc, msg);
4371 free (msg);
4373 desc = info->descriptor;
4375 /* This is the run-time equivalent of resolve.c's
4376 check_dimension(). The logical is more readable there
4377 than it is here, with all the trees. */
4378 lbound = gfc_conv_array_lbound (desc, dim);
4379 end = info->end[dim];
4380 if (check_upper)
4381 ubound = gfc_conv_array_ubound (desc, dim);
4382 else
4383 ubound = NULL;
4385 /* non_zerosized is true when the selected range is not
4386 empty. */
4387 stride_pos = fold_build2_loc (input_location, GT_EXPR,
4388 logical_type_node, info->stride[dim],
4389 gfc_index_zero_node);
4390 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4391 info->start[dim], end);
4392 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4393 logical_type_node, stride_pos, tmp);
4395 stride_neg = fold_build2_loc (input_location, LT_EXPR,
4396 logical_type_node,
4397 info->stride[dim], gfc_index_zero_node);
4398 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
4399 info->start[dim], end);
4400 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4401 logical_type_node,
4402 stride_neg, tmp);
4403 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4404 logical_type_node,
4405 stride_pos, stride_neg);
4407 /* Check the start of the range against the lower and upper
4408 bounds of the array, if the range is not empty.
4409 If upper bound is present, include both bounds in the
4410 error message. */
4411 if (check_upper)
4413 tmp = fold_build2_loc (input_location, LT_EXPR,
4414 logical_type_node,
4415 info->start[dim], lbound);
4416 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4417 logical_type_node,
4418 non_zerosized, tmp);
4419 tmp2 = fold_build2_loc (input_location, GT_EXPR,
4420 logical_type_node,
4421 info->start[dim], ubound);
4422 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4423 logical_type_node,
4424 non_zerosized, tmp2);
4425 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4426 "outside of expected range (%%ld:%%ld)",
4427 dim + 1, expr_name);
4428 gfc_trans_runtime_check (true, false, tmp, &inner,
4429 expr_loc, msg,
4430 fold_convert (long_integer_type_node, info->start[dim]),
4431 fold_convert (long_integer_type_node, lbound),
4432 fold_convert (long_integer_type_node, ubound));
4433 gfc_trans_runtime_check (true, false, tmp2, &inner,
4434 expr_loc, msg,
4435 fold_convert (long_integer_type_node, info->start[dim]),
4436 fold_convert (long_integer_type_node, lbound),
4437 fold_convert (long_integer_type_node, ubound));
4438 free (msg);
4440 else
4442 tmp = fold_build2_loc (input_location, LT_EXPR,
4443 logical_type_node,
4444 info->start[dim], lbound);
4445 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4446 logical_type_node, non_zerosized, tmp);
4447 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4448 "below lower bound of %%ld",
4449 dim + 1, expr_name);
4450 gfc_trans_runtime_check (true, false, tmp, &inner,
4451 expr_loc, msg,
4452 fold_convert (long_integer_type_node, info->start[dim]),
4453 fold_convert (long_integer_type_node, lbound));
4454 free (msg);
4457 /* Compute the last element of the range, which is not
4458 necessarily "end" (think 0:5:3, which doesn't contain 5)
4459 and check it against both lower and upper bounds. */
4461 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4462 gfc_array_index_type, end,
4463 info->start[dim]);
4464 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
4465 gfc_array_index_type, tmp,
4466 info->stride[dim]);
4467 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4468 gfc_array_index_type, end, tmp);
4469 tmp2 = fold_build2_loc (input_location, LT_EXPR,
4470 logical_type_node, tmp, lbound);
4471 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4472 logical_type_node, non_zerosized, tmp2);
4473 if (check_upper)
4475 tmp3 = fold_build2_loc (input_location, GT_EXPR,
4476 logical_type_node, tmp, ubound);
4477 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4478 logical_type_node, non_zerosized, tmp3);
4479 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4480 "outside of expected range (%%ld:%%ld)",
4481 dim + 1, expr_name);
4482 gfc_trans_runtime_check (true, false, tmp2, &inner,
4483 expr_loc, msg,
4484 fold_convert (long_integer_type_node, tmp),
4485 fold_convert (long_integer_type_node, ubound),
4486 fold_convert (long_integer_type_node, lbound));
4487 gfc_trans_runtime_check (true, false, tmp3, &inner,
4488 expr_loc, msg,
4489 fold_convert (long_integer_type_node, tmp),
4490 fold_convert (long_integer_type_node, ubound),
4491 fold_convert (long_integer_type_node, lbound));
4492 free (msg);
4494 else
4496 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4497 "below lower bound of %%ld",
4498 dim + 1, expr_name);
4499 gfc_trans_runtime_check (true, false, tmp2, &inner,
4500 expr_loc, msg,
4501 fold_convert (long_integer_type_node, tmp),
4502 fold_convert (long_integer_type_node, lbound));
4503 free (msg);
4506 /* Check the section sizes match. */
4507 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4508 gfc_array_index_type, end,
4509 info->start[dim]);
4510 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4511 gfc_array_index_type, tmp,
4512 info->stride[dim]);
4513 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4514 gfc_array_index_type,
4515 gfc_index_one_node, tmp);
4516 tmp = fold_build2_loc (input_location, MAX_EXPR,
4517 gfc_array_index_type, tmp,
4518 build_int_cst (gfc_array_index_type, 0));
4519 /* We remember the size of the first section, and check all the
4520 others against this. */
4521 if (size[n])
4523 tmp3 = fold_build2_loc (input_location, NE_EXPR,
4524 logical_type_node, tmp, size[n]);
4525 msg = xasprintf ("Array bound mismatch for dimension %d "
4526 "of array '%s' (%%ld/%%ld)",
4527 dim + 1, expr_name);
4529 gfc_trans_runtime_check (true, false, tmp3, &inner,
4530 expr_loc, msg,
4531 fold_convert (long_integer_type_node, tmp),
4532 fold_convert (long_integer_type_node, size[n]));
4534 free (msg);
4536 else
4537 size[n] = gfc_evaluate_now (tmp, &inner);
4540 tmp = gfc_finish_block (&inner);
4542 /* For optional arguments, only check bounds if the argument is
4543 present. */
4544 if (expr->symtree->n.sym->attr.optional
4545 || expr->symtree->n.sym->attr.not_always_present)
4546 tmp = build3_v (COND_EXPR,
4547 gfc_conv_expr_present (expr->symtree->n.sym),
4548 tmp, build_empty_stmt (input_location));
4550 gfc_add_expr_to_block (&block, tmp);
4554 tmp = gfc_finish_block (&block);
4555 gfc_add_expr_to_block (&outer_loop->pre, tmp);
4558 for (loop = loop->nested; loop; loop = loop->next)
4559 gfc_conv_ss_startstride (loop);
4562 /* Return true if both symbols could refer to the same data object. Does
4563 not take account of aliasing due to equivalence statements. */
4565 static int
4566 symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
4567 bool lsym_target, bool rsym_pointer, bool rsym_target)
4569 /* Aliasing isn't possible if the symbols have different base types. */
4570 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
4571 return 0;
4573 /* Pointers can point to other pointers and target objects. */
4575 if ((lsym_pointer && (rsym_pointer || rsym_target))
4576 || (rsym_pointer && (lsym_pointer || lsym_target)))
4577 return 1;
4579 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
4580 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
4581 checked above. */
4582 if (lsym_target && rsym_target
4583 && ((lsym->attr.dummy && !lsym->attr.contiguous
4584 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
4585 || (rsym->attr.dummy && !rsym->attr.contiguous
4586 && (!rsym->attr.dimension
4587 || rsym->as->type == AS_ASSUMED_SHAPE))))
4588 return 1;
4590 return 0;
4594 /* Return true if the two SS could be aliased, i.e. both point to the same data
4595 object. */
4596 /* TODO: resolve aliases based on frontend expressions. */
4598 static int
4599 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
4601 gfc_ref *lref;
4602 gfc_ref *rref;
4603 gfc_expr *lexpr, *rexpr;
4604 gfc_symbol *lsym;
4605 gfc_symbol *rsym;
4606 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
4608 lexpr = lss->info->expr;
4609 rexpr = rss->info->expr;
4611 lsym = lexpr->symtree->n.sym;
4612 rsym = rexpr->symtree->n.sym;
4614 lsym_pointer = lsym->attr.pointer;
4615 lsym_target = lsym->attr.target;
4616 rsym_pointer = rsym->attr.pointer;
4617 rsym_target = rsym->attr.target;
4619 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
4620 rsym_pointer, rsym_target))
4621 return 1;
4623 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
4624 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
4625 return 0;
4627 /* For derived types we must check all the component types. We can ignore
4628 array references as these will have the same base type as the previous
4629 component ref. */
4630 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
4632 if (lref->type != REF_COMPONENT)
4633 continue;
4635 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
4636 lsym_target = lsym_target || lref->u.c.sym->attr.target;
4638 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
4639 rsym_pointer, rsym_target))
4640 return 1;
4642 if ((lsym_pointer && (rsym_pointer || rsym_target))
4643 || (rsym_pointer && (lsym_pointer || lsym_target)))
4645 if (gfc_compare_types (&lref->u.c.component->ts,
4646 &rsym->ts))
4647 return 1;
4650 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
4651 rref = rref->next)
4653 if (rref->type != REF_COMPONENT)
4654 continue;
4656 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4657 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4659 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
4660 lsym_pointer, lsym_target,
4661 rsym_pointer, rsym_target))
4662 return 1;
4664 if ((lsym_pointer && (rsym_pointer || rsym_target))
4665 || (rsym_pointer && (lsym_pointer || lsym_target)))
4667 if (gfc_compare_types (&lref->u.c.component->ts,
4668 &rref->u.c.sym->ts))
4669 return 1;
4670 if (gfc_compare_types (&lref->u.c.sym->ts,
4671 &rref->u.c.component->ts))
4672 return 1;
4673 if (gfc_compare_types (&lref->u.c.component->ts,
4674 &rref->u.c.component->ts))
4675 return 1;
4680 lsym_pointer = lsym->attr.pointer;
4681 lsym_target = lsym->attr.target;
4682 lsym_pointer = lsym->attr.pointer;
4683 lsym_target = lsym->attr.target;
4685 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
4687 if (rref->type != REF_COMPONENT)
4688 break;
4690 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4691 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4693 if (symbols_could_alias (rref->u.c.sym, lsym,
4694 lsym_pointer, lsym_target,
4695 rsym_pointer, rsym_target))
4696 return 1;
4698 if ((lsym_pointer && (rsym_pointer || rsym_target))
4699 || (rsym_pointer && (lsym_pointer || lsym_target)))
4701 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
4702 return 1;
4706 return 0;
4710 /* Resolve array data dependencies. Creates a temporary if required. */
4711 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
4712 dependency.c. */
4714 void
4715 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
4716 gfc_ss * rss)
4718 gfc_ss *ss;
4719 gfc_ref *lref;
4720 gfc_ref *rref;
4721 gfc_ss_info *ss_info;
4722 gfc_expr *dest_expr;
4723 gfc_expr *ss_expr;
4724 int nDepend = 0;
4725 int i, j;
4727 loop->temp_ss = NULL;
4728 dest_expr = dest->info->expr;
4730 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
4732 ss_info = ss->info;
4733 ss_expr = ss_info->expr;
4735 if (ss_info->array_outer_dependency)
4737 nDepend = 1;
4738 break;
4741 if (ss_info->type != GFC_SS_SECTION)
4743 if (flag_realloc_lhs
4744 && dest_expr != ss_expr
4745 && gfc_is_reallocatable_lhs (dest_expr)
4746 && ss_expr->rank)
4747 nDepend = gfc_check_dependency (dest_expr, ss_expr, true);
4749 /* Check for cases like c(:)(1:2) = c(2)(2:3) */
4750 if (!nDepend && dest_expr->rank > 0
4751 && dest_expr->ts.type == BT_CHARACTER
4752 && ss_expr->expr_type == EXPR_VARIABLE)
4754 nDepend = gfc_check_dependency (dest_expr, ss_expr, false);
4756 if (ss_info->type == GFC_SS_REFERENCE
4757 && gfc_check_dependency (dest_expr, ss_expr, false))
4758 ss_info->data.scalar.needs_temporary = 1;
4760 if (nDepend)
4761 break;
4762 else
4763 continue;
4766 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
4768 if (gfc_could_be_alias (dest, ss)
4769 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
4771 nDepend = 1;
4772 break;
4775 else
4777 lref = dest_expr->ref;
4778 rref = ss_expr->ref;
4780 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
4782 if (nDepend == 1)
4783 break;
4785 for (i = 0; i < dest->dimen; i++)
4786 for (j = 0; j < ss->dimen; j++)
4787 if (i != j
4788 && dest->dim[i] == ss->dim[j])
4790 /* If we don't access array elements in the same order,
4791 there is a dependency. */
4792 nDepend = 1;
4793 goto temporary;
4795 #if 0
4796 /* TODO : loop shifting. */
4797 if (nDepend == 1)
4799 /* Mark the dimensions for LOOP SHIFTING */
4800 for (n = 0; n < loop->dimen; n++)
4802 int dim = dest->data.info.dim[n];
4804 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
4805 depends[n] = 2;
4806 else if (! gfc_is_same_range (&lref->u.ar,
4807 &rref->u.ar, dim, 0))
4808 depends[n] = 1;
4811 /* Put all the dimensions with dependencies in the
4812 innermost loops. */
4813 dim = 0;
4814 for (n = 0; n < loop->dimen; n++)
4816 gcc_assert (loop->order[n] == n);
4817 if (depends[n])
4818 loop->order[dim++] = n;
4820 for (n = 0; n < loop->dimen; n++)
4822 if (! depends[n])
4823 loop->order[dim++] = n;
4826 gcc_assert (dim == loop->dimen);
4827 break;
4829 #endif
4833 temporary:
4835 if (nDepend == 1)
4837 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
4838 if (GFC_ARRAY_TYPE_P (base_type)
4839 || GFC_DESCRIPTOR_TYPE_P (base_type))
4840 base_type = gfc_get_element_type (base_type);
4841 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
4842 loop->dimen);
4843 gfc_add_ss_to_loop (loop, loop->temp_ss);
4845 else
4846 loop->temp_ss = NULL;
4850 /* Browse through each array's information from the scalarizer and set the loop
4851 bounds according to the "best" one (per dimension), i.e. the one which
4852 provides the most information (constant bounds, shape, etc.). */
4854 static void
4855 set_loop_bounds (gfc_loopinfo *loop)
4857 int n, dim, spec_dim;
4858 gfc_array_info *info;
4859 gfc_array_info *specinfo;
4860 gfc_ss *ss;
4861 tree tmp;
4862 gfc_ss **loopspec;
4863 bool dynamic[GFC_MAX_DIMENSIONS];
4864 mpz_t *cshape;
4865 mpz_t i;
4866 bool nonoptional_arr;
4868 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4870 loopspec = loop->specloop;
4872 mpz_init (i);
4873 for (n = 0; n < loop->dimen; n++)
4875 loopspec[n] = NULL;
4876 dynamic[n] = false;
4878 /* If there are both optional and nonoptional array arguments, scalarize
4879 over the nonoptional; otherwise, it does not matter as then all
4880 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
4882 nonoptional_arr = false;
4884 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4885 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
4886 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
4888 nonoptional_arr = true;
4889 break;
4892 /* We use one SS term, and use that to determine the bounds of the
4893 loop for this dimension. We try to pick the simplest term. */
4894 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4896 gfc_ss_type ss_type;
4898 ss_type = ss->info->type;
4899 if (ss_type == GFC_SS_SCALAR
4900 || ss_type == GFC_SS_TEMP
4901 || ss_type == GFC_SS_REFERENCE
4902 || (ss->info->can_be_null_ref && nonoptional_arr))
4903 continue;
4905 info = &ss->info->data.array;
4906 dim = ss->dim[n];
4908 if (loopspec[n] != NULL)
4910 specinfo = &loopspec[n]->info->data.array;
4911 spec_dim = loopspec[n]->dim[n];
4913 else
4915 /* Silence uninitialized warnings. */
4916 specinfo = NULL;
4917 spec_dim = 0;
4920 if (info->shape)
4922 gcc_assert (info->shape[dim]);
4923 /* The frontend has worked out the size for us. */
4924 if (!loopspec[n]
4925 || !specinfo->shape
4926 || !integer_zerop (specinfo->start[spec_dim]))
4927 /* Prefer zero-based descriptors if possible. */
4928 loopspec[n] = ss;
4929 continue;
4932 if (ss_type == GFC_SS_CONSTRUCTOR)
4934 gfc_constructor_base base;
4935 /* An unknown size constructor will always be rank one.
4936 Higher rank constructors will either have known shape,
4937 or still be wrapped in a call to reshape. */
4938 gcc_assert (loop->dimen == 1);
4940 /* Always prefer to use the constructor bounds if the size
4941 can be determined at compile time. Prefer not to otherwise,
4942 since the general case involves realloc, and it's better to
4943 avoid that overhead if possible. */
4944 base = ss->info->expr->value.constructor;
4945 dynamic[n] = gfc_get_array_constructor_size (&i, base);
4946 if (!dynamic[n] || !loopspec[n])
4947 loopspec[n] = ss;
4948 continue;
4951 /* Avoid using an allocatable lhs in an assignment, since
4952 there might be a reallocation coming. */
4953 if (loopspec[n] && ss->is_alloc_lhs)
4954 continue;
4956 if (!loopspec[n])
4957 loopspec[n] = ss;
4958 /* Criteria for choosing a loop specifier (most important first):
4959 doesn't need realloc
4960 stride of one
4961 known stride
4962 known lower bound
4963 known upper bound
4965 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
4966 loopspec[n] = ss;
4967 else if (integer_onep (info->stride[dim])
4968 && !integer_onep (specinfo->stride[spec_dim]))
4969 loopspec[n] = ss;
4970 else if (INTEGER_CST_P (info->stride[dim])
4971 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
4972 loopspec[n] = ss;
4973 else if (INTEGER_CST_P (info->start[dim])
4974 && !INTEGER_CST_P (specinfo->start[spec_dim])
4975 && integer_onep (info->stride[dim])
4976 == integer_onep (specinfo->stride[spec_dim])
4977 && INTEGER_CST_P (info->stride[dim])
4978 == INTEGER_CST_P (specinfo->stride[spec_dim]))
4979 loopspec[n] = ss;
4980 /* We don't work out the upper bound.
4981 else if (INTEGER_CST_P (info->finish[n])
4982 && ! INTEGER_CST_P (specinfo->finish[n]))
4983 loopspec[n] = ss; */
4986 /* We should have found the scalarization loop specifier. If not,
4987 that's bad news. */
4988 gcc_assert (loopspec[n]);
4990 info = &loopspec[n]->info->data.array;
4991 dim = loopspec[n]->dim[n];
4993 /* Set the extents of this range. */
4994 cshape = info->shape;
4995 if (cshape && INTEGER_CST_P (info->start[dim])
4996 && INTEGER_CST_P (info->stride[dim]))
4998 loop->from[n] = info->start[dim];
4999 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
5000 mpz_sub_ui (i, i, 1);
5001 /* To = from + (size - 1) * stride. */
5002 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
5003 if (!integer_onep (info->stride[dim]))
5004 tmp = fold_build2_loc (input_location, MULT_EXPR,
5005 gfc_array_index_type, tmp,
5006 info->stride[dim]);
5007 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
5008 gfc_array_index_type,
5009 loop->from[n], tmp);
5011 else
5013 loop->from[n] = info->start[dim];
5014 switch (loopspec[n]->info->type)
5016 case GFC_SS_CONSTRUCTOR:
5017 /* The upper bound is calculated when we expand the
5018 constructor. */
5019 gcc_assert (loop->to[n] == NULL_TREE);
5020 break;
5022 case GFC_SS_SECTION:
5023 /* Use the end expression if it exists and is not constant,
5024 so that it is only evaluated once. */
5025 loop->to[n] = info->end[dim];
5026 break;
5028 case GFC_SS_FUNCTION:
5029 /* The loop bound will be set when we generate the call. */
5030 gcc_assert (loop->to[n] == NULL_TREE);
5031 break;
5033 case GFC_SS_INTRINSIC:
5035 gfc_expr *expr = loopspec[n]->info->expr;
5037 /* The {l,u}bound of an assumed rank. */
5038 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
5039 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
5040 && expr->value.function.actual->next->expr == NULL
5041 && expr->value.function.actual->expr->rank == -1);
5043 loop->to[n] = info->end[dim];
5044 break;
5047 case GFC_SS_COMPONENT:
5049 if (info->end[dim] != NULL_TREE)
5051 loop->to[n] = info->end[dim];
5052 break;
5054 else
5055 gcc_unreachable ();
5058 default:
5059 gcc_unreachable ();
5063 /* Transform everything so we have a simple incrementing variable. */
5064 if (integer_onep (info->stride[dim]))
5065 info->delta[dim] = gfc_index_zero_node;
5066 else
5068 /* Set the delta for this section. */
5069 info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre);
5070 /* Number of iterations is (end - start + step) / step.
5071 with start = 0, this simplifies to
5072 last = end / step;
5073 for (i = 0; i<=last; i++){...}; */
5074 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5075 gfc_array_index_type, loop->to[n],
5076 loop->from[n]);
5077 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
5078 gfc_array_index_type, tmp, info->stride[dim]);
5079 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5080 tmp, build_int_cst (gfc_array_index_type, -1));
5081 loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre);
5082 /* Make the loop variable start at 0. */
5083 loop->from[n] = gfc_index_zero_node;
5086 mpz_clear (i);
5088 for (loop = loop->nested; loop; loop = loop->next)
5089 set_loop_bounds (loop);
5093 /* Initialize the scalarization loop. Creates the loop variables. Determines
5094 the range of the loop variables. Creates a temporary if required.
5095 Also generates code for scalar expressions which have been
5096 moved outside the loop. */
5098 void
5099 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
5101 gfc_ss *tmp_ss;
5102 tree tmp;
5104 set_loop_bounds (loop);
5106 /* Add all the scalar code that can be taken out of the loops.
5107 This may include calculating the loop bounds, so do it before
5108 allocating the temporary. */
5109 gfc_add_loop_ss_code (loop, loop->ss, false, where);
5111 tmp_ss = loop->temp_ss;
5112 /* If we want a temporary then create it. */
5113 if (tmp_ss != NULL)
5115 gfc_ss_info *tmp_ss_info;
5117 tmp_ss_info = tmp_ss->info;
5118 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
5119 gcc_assert (loop->parent == NULL);
5121 /* Make absolutely sure that this is a complete type. */
5122 if (tmp_ss_info->string_length)
5123 tmp_ss_info->data.temp.type
5124 = gfc_get_character_type_len_for_eltype
5125 (TREE_TYPE (tmp_ss_info->data.temp.type),
5126 tmp_ss_info->string_length);
5128 tmp = tmp_ss_info->data.temp.type;
5129 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
5130 tmp_ss_info->type = GFC_SS_SECTION;
5132 gcc_assert (tmp_ss->dimen != 0);
5134 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
5135 NULL_TREE, false, true, false, where);
5138 /* For array parameters we don't have loop variables, so don't calculate the
5139 translations. */
5140 if (!loop->array_parameter)
5141 gfc_set_delta (loop);
5145 /* Calculates how to transform from loop variables to array indices for each
5146 array: once loop bounds are chosen, sets the difference (DELTA field) between
5147 loop bounds and array reference bounds, for each array info. */
5149 void
5150 gfc_set_delta (gfc_loopinfo *loop)
5152 gfc_ss *ss, **loopspec;
5153 gfc_array_info *info;
5154 tree tmp;
5155 int n, dim;
5157 gfc_loopinfo * const outer_loop = outermost_loop (loop);
5159 loopspec = loop->specloop;
5161 /* Calculate the translation from loop variables to array indices. */
5162 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5164 gfc_ss_type ss_type;
5166 ss_type = ss->info->type;
5167 if (ss_type != GFC_SS_SECTION
5168 && ss_type != GFC_SS_COMPONENT
5169 && ss_type != GFC_SS_CONSTRUCTOR)
5170 continue;
5172 info = &ss->info->data.array;
5174 for (n = 0; n < ss->dimen; n++)
5176 /* If we are specifying the range the delta is already set. */
5177 if (loopspec[n] != ss)
5179 dim = ss->dim[n];
5181 /* Calculate the offset relative to the loop variable.
5182 First multiply by the stride. */
5183 tmp = loop->from[n];
5184 if (!integer_onep (info->stride[dim]))
5185 tmp = fold_build2_loc (input_location, MULT_EXPR,
5186 gfc_array_index_type,
5187 tmp, info->stride[dim]);
5189 /* Then subtract this from our starting value. */
5190 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5191 gfc_array_index_type,
5192 info->start[dim], tmp);
5194 info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
5199 for (loop = loop->nested; loop; loop = loop->next)
5200 gfc_set_delta (loop);
5204 /* Calculate the size of a given array dimension from the bounds. This
5205 is simply (ubound - lbound + 1) if this expression is positive
5206 or 0 if it is negative (pick either one if it is zero). Optionally
5207 (if or_expr is present) OR the (expression != 0) condition to it. */
5209 tree
5210 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
5212 tree res;
5213 tree cond;
5215 /* Calculate (ubound - lbound + 1). */
5216 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5217 ubound, lbound);
5218 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
5219 gfc_index_one_node);
5221 /* Check whether the size for this dimension is negative. */
5222 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, res,
5223 gfc_index_zero_node);
5224 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
5225 gfc_index_zero_node, res);
5227 /* Build OR expression. */
5228 if (or_expr)
5229 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
5230 logical_type_node, *or_expr, cond);
5232 return res;
5236 /* For an array descriptor, get the total number of elements. This is just
5237 the product of the extents along from_dim to to_dim. */
5239 static tree
5240 gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
5242 tree res;
5243 int dim;
5245 res = gfc_index_one_node;
5247 for (dim = from_dim; dim < to_dim; ++dim)
5249 tree lbound;
5250 tree ubound;
5251 tree extent;
5253 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
5254 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
5256 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
5257 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5258 res, extent);
5261 return res;
5265 /* Full size of an array. */
5267 tree
5268 gfc_conv_descriptor_size (tree desc, int rank)
5270 return gfc_conv_descriptor_size_1 (desc, 0, rank);
5274 /* Size of a coarray for all dimensions but the last. */
5276 tree
5277 gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
5279 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
5283 /* Fills in an array descriptor, and returns the size of the array.
5284 The size will be a simple_val, ie a variable or a constant. Also
5285 calculates the offset of the base. The pointer argument overflow,
5286 which should be of integer type, will increase in value if overflow
5287 occurs during the size calculation. Returns the size of the array.
5289 stride = 1;
5290 offset = 0;
5291 for (n = 0; n < rank; n++)
5293 a.lbound[n] = specified_lower_bound;
5294 offset = offset + a.lbond[n] * stride;
5295 size = 1 - lbound;
5296 a.ubound[n] = specified_upper_bound;
5297 a.stride[n] = stride;
5298 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
5299 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
5300 stride = stride * size;
5302 for (n = rank; n < rank+corank; n++)
5303 (Set lcobound/ucobound as above.)
5304 element_size = sizeof (array element);
5305 if (!rank)
5306 return element_size
5307 stride = (size_t) stride;
5308 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
5309 stride = stride * element_size;
5310 return (stride);
5311 } */
5312 /*GCC ARRAYS*/
5314 static tree
5315 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
5316 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
5317 stmtblock_t * descriptor_block, tree * overflow,
5318 tree expr3_elem_size, tree *nelems, gfc_expr *expr3,
5319 tree expr3_desc, bool e3_is_array_constr, gfc_expr *expr)
5321 tree type;
5322 tree tmp;
5323 tree size;
5324 tree offset;
5325 tree stride;
5326 tree element_size;
5327 tree or_expr;
5328 tree thencase;
5329 tree elsecase;
5330 tree cond;
5331 tree var;
5332 stmtblock_t thenblock;
5333 stmtblock_t elseblock;
5334 gfc_expr *ubound;
5335 gfc_se se;
5336 int n;
5338 type = TREE_TYPE (descriptor);
5340 stride = gfc_index_one_node;
5341 offset = gfc_index_zero_node;
5343 /* Set the dtype before the alloc, because registration of coarrays needs
5344 it initialized. */
5345 if (expr->ts.type == BT_CHARACTER
5346 && expr->ts.deferred
5347 && VAR_P (expr->ts.u.cl->backend_decl))
5349 type = gfc_typenode_for_spec (&expr->ts);
5350 tmp = gfc_conv_descriptor_dtype (descriptor);
5351 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
5353 else
5355 tmp = gfc_conv_descriptor_dtype (descriptor);
5356 gfc_add_modify (pblock, tmp, gfc_get_dtype (type));
5359 or_expr = logical_false_node;
5361 for (n = 0; n < rank; n++)
5363 tree conv_lbound;
5364 tree conv_ubound;
5366 /* We have 3 possibilities for determining the size of the array:
5367 lower == NULL => lbound = 1, ubound = upper[n]
5368 upper[n] = NULL => lbound = 1, ubound = lower[n]
5369 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
5370 ubound = upper[n];
5372 /* Set lower bound. */
5373 gfc_init_se (&se, NULL);
5374 if (expr3_desc != NULL_TREE)
5376 if (e3_is_array_constr)
5377 /* The lbound of a constant array [] starts at zero, but when
5378 allocating it, the standard expects the array to start at
5379 one. */
5380 se.expr = gfc_index_one_node;
5381 else
5382 se.expr = gfc_conv_descriptor_lbound_get (expr3_desc,
5383 gfc_rank_cst[n]);
5385 else if (lower == NULL)
5386 se.expr = gfc_index_one_node;
5387 else
5389 gcc_assert (lower[n]);
5390 if (ubound)
5392 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5393 gfc_add_block_to_block (pblock, &se.pre);
5395 else
5397 se.expr = gfc_index_one_node;
5398 ubound = lower[n];
5401 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5402 gfc_rank_cst[n], se.expr);
5403 conv_lbound = se.expr;
5405 /* Work out the offset for this component. */
5406 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5407 se.expr, stride);
5408 offset = fold_build2_loc (input_location, MINUS_EXPR,
5409 gfc_array_index_type, offset, tmp);
5411 /* Set upper bound. */
5412 gfc_init_se (&se, NULL);
5413 if (expr3_desc != NULL_TREE)
5415 if (e3_is_array_constr)
5417 /* The lbound of a constant array [] starts at zero, but when
5418 allocating it, the standard expects the array to start at
5419 one. Therefore fix the upper bound to be
5420 (desc.ubound - desc.lbound)+ 1. */
5421 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5422 gfc_array_index_type,
5423 gfc_conv_descriptor_ubound_get (
5424 expr3_desc, gfc_rank_cst[n]),
5425 gfc_conv_descriptor_lbound_get (
5426 expr3_desc, gfc_rank_cst[n]));
5427 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5428 gfc_array_index_type, tmp,
5429 gfc_index_one_node);
5430 se.expr = gfc_evaluate_now (tmp, pblock);
5432 else
5433 se.expr = gfc_conv_descriptor_ubound_get (expr3_desc,
5434 gfc_rank_cst[n]);
5436 else
5438 gcc_assert (ubound);
5439 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5440 gfc_add_block_to_block (pblock, &se.pre);
5441 if (ubound->expr_type == EXPR_FUNCTION)
5442 se.expr = gfc_evaluate_now (se.expr, pblock);
5444 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
5445 gfc_rank_cst[n], se.expr);
5446 conv_ubound = se.expr;
5448 /* Store the stride. */
5449 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
5450 gfc_rank_cst[n], stride);
5452 /* Calculate size and check whether extent is negative. */
5453 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
5454 size = gfc_evaluate_now (size, pblock);
5456 /* Check whether multiplying the stride by the number of
5457 elements in this dimension would overflow. We must also check
5458 whether the current dimension has zero size in order to avoid
5459 division by zero.
5461 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5462 gfc_array_index_type,
5463 fold_convert (gfc_array_index_type,
5464 TYPE_MAX_VALUE (gfc_array_index_type)),
5465 size);
5466 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5467 logical_type_node, tmp, stride),
5468 PRED_FORTRAN_OVERFLOW);
5469 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5470 integer_one_node, integer_zero_node);
5471 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5472 logical_type_node, size,
5473 gfc_index_zero_node),
5474 PRED_FORTRAN_SIZE_ZERO);
5475 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5476 integer_zero_node, tmp);
5477 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5478 *overflow, tmp);
5479 *overflow = gfc_evaluate_now (tmp, pblock);
5481 /* Multiply the stride by the number of elements in this dimension. */
5482 stride = fold_build2_loc (input_location, MULT_EXPR,
5483 gfc_array_index_type, stride, size);
5484 stride = gfc_evaluate_now (stride, pblock);
5487 for (n = rank; n < rank + corank; n++)
5489 ubound = upper[n];
5491 /* Set lower bound. */
5492 gfc_init_se (&se, NULL);
5493 if (lower == NULL || lower[n] == NULL)
5495 gcc_assert (n == rank + corank - 1);
5496 se.expr = gfc_index_one_node;
5498 else
5500 if (ubound || n == rank + corank - 1)
5502 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5503 gfc_add_block_to_block (pblock, &se.pre);
5505 else
5507 se.expr = gfc_index_one_node;
5508 ubound = lower[n];
5511 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5512 gfc_rank_cst[n], se.expr);
5514 if (n < rank + corank - 1)
5516 gfc_init_se (&se, NULL);
5517 gcc_assert (ubound);
5518 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5519 gfc_add_block_to_block (pblock, &se.pre);
5520 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
5521 gfc_rank_cst[n], se.expr);
5525 /* The stride is the number of elements in the array, so multiply by the
5526 size of an element to get the total size. Obviously, if there is a
5527 SOURCE expression (expr3) we must use its element size. */
5528 if (expr3_elem_size != NULL_TREE)
5529 tmp = expr3_elem_size;
5530 else if (expr3 != NULL)
5532 if (expr3->ts.type == BT_CLASS)
5534 gfc_se se_sz;
5535 gfc_expr *sz = gfc_copy_expr (expr3);
5536 gfc_add_vptr_component (sz);
5537 gfc_add_size_component (sz);
5538 gfc_init_se (&se_sz, NULL);
5539 gfc_conv_expr (&se_sz, sz);
5540 gfc_free_expr (sz);
5541 tmp = se_sz.expr;
5543 else
5545 tmp = gfc_typenode_for_spec (&expr3->ts);
5546 tmp = TYPE_SIZE_UNIT (tmp);
5549 else
5550 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5552 /* Convert to size_t. */
5553 element_size = fold_convert (size_type_node, tmp);
5555 if (rank == 0)
5556 return element_size;
5558 *nelems = gfc_evaluate_now (stride, pblock);
5559 stride = fold_convert (size_type_node, stride);
5561 /* First check for overflow. Since an array of type character can
5562 have zero element_size, we must check for that before
5563 dividing. */
5564 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5565 size_type_node,
5566 TYPE_MAX_VALUE (size_type_node), element_size);
5567 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5568 logical_type_node, tmp, stride),
5569 PRED_FORTRAN_OVERFLOW);
5570 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5571 integer_one_node, integer_zero_node);
5572 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5573 logical_type_node, element_size,
5574 build_int_cst (size_type_node, 0)),
5575 PRED_FORTRAN_SIZE_ZERO);
5576 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5577 integer_zero_node, tmp);
5578 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5579 *overflow, tmp);
5580 *overflow = gfc_evaluate_now (tmp, pblock);
5582 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
5583 stride, element_size);
5585 if (poffset != NULL)
5587 offset = gfc_evaluate_now (offset, pblock);
5588 *poffset = offset;
5591 if (integer_zerop (or_expr))
5592 return size;
5593 if (integer_onep (or_expr))
5594 return build_int_cst (size_type_node, 0);
5596 var = gfc_create_var (TREE_TYPE (size), "size");
5597 gfc_start_block (&thenblock);
5598 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
5599 thencase = gfc_finish_block (&thenblock);
5601 gfc_start_block (&elseblock);
5602 gfc_add_modify (&elseblock, var, size);
5603 elsecase = gfc_finish_block (&elseblock);
5605 tmp = gfc_evaluate_now (or_expr, pblock);
5606 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
5607 gfc_add_expr_to_block (pblock, tmp);
5609 return var;
5613 /* Retrieve the last ref from the chain. This routine is specific to
5614 gfc_array_allocate ()'s needs. */
5616 bool
5617 retrieve_last_ref (gfc_ref **ref_in, gfc_ref **prev_ref_in)
5619 gfc_ref *ref, *prev_ref;
5621 ref = *ref_in;
5622 /* Prevent warnings for uninitialized variables. */
5623 prev_ref = *prev_ref_in;
5624 while (ref && ref->next != NULL)
5626 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
5627 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
5628 prev_ref = ref;
5629 ref = ref->next;
5632 if (ref == NULL || ref->type != REF_ARRAY)
5633 return false;
5635 *ref_in = ref;
5636 *prev_ref_in = prev_ref;
5637 return true;
5640 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
5641 the work for an ALLOCATE statement. */
5642 /*GCC ARRAYS*/
5644 bool
5645 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
5646 tree errlen, tree label_finish, tree expr3_elem_size,
5647 tree *nelems, gfc_expr *expr3, tree e3_arr_desc,
5648 bool e3_is_array_constr)
5650 tree tmp;
5651 tree pointer;
5652 tree offset = NULL_TREE;
5653 tree token = NULL_TREE;
5654 tree size;
5655 tree msg;
5656 tree error = NULL_TREE;
5657 tree overflow; /* Boolean storing whether size calculation overflows. */
5658 tree var_overflow = NULL_TREE;
5659 tree cond;
5660 tree set_descriptor;
5661 stmtblock_t set_descriptor_block;
5662 stmtblock_t elseblock;
5663 gfc_expr **lower;
5664 gfc_expr **upper;
5665 gfc_ref *ref, *prev_ref = NULL, *coref;
5666 bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false,
5667 non_ulimate_coarray_ptr_comp;
5669 ref = expr->ref;
5671 /* Find the last reference in the chain. */
5672 if (!retrieve_last_ref (&ref, &prev_ref))
5673 return false;
5675 /* Take the allocatable and coarray properties solely from the expr-ref's
5676 attributes and not from source=-expression. */
5677 if (!prev_ref)
5679 allocatable = expr->symtree->n.sym->attr.allocatable;
5680 dimension = expr->symtree->n.sym->attr.dimension;
5681 non_ulimate_coarray_ptr_comp = false;
5683 else
5685 allocatable = prev_ref->u.c.component->attr.allocatable;
5686 /* Pointer components in coarrayed derived types must be treated
5687 specially in that they are registered without a check if the are
5688 already associated. This does not hold for ultimate coarray
5689 pointers. */
5690 non_ulimate_coarray_ptr_comp = (prev_ref->u.c.component->attr.pointer
5691 && !prev_ref->u.c.component->attr.codimension);
5692 dimension = prev_ref->u.c.component->attr.dimension;
5695 /* For allocatable/pointer arrays in derived types, one of the refs has to be
5696 a coarray. In this case it does not matter whether we are on this_image
5697 or not. */
5698 coarray = false;
5699 for (coref = expr->ref; coref; coref = coref->next)
5700 if (coref->type == REF_ARRAY && coref->u.ar.codimen > 0)
5702 coarray = true;
5703 break;
5706 if (!dimension)
5707 gcc_assert (coarray);
5709 if (ref->u.ar.type == AR_FULL && expr3 != NULL)
5711 gfc_ref *old_ref = ref;
5712 /* F08:C633: Array shape from expr3. */
5713 ref = expr3->ref;
5715 /* Find the last reference in the chain. */
5716 if (!retrieve_last_ref (&ref, &prev_ref))
5718 if (expr3->expr_type == EXPR_FUNCTION
5719 && gfc_expr_attr (expr3).dimension)
5720 ref = old_ref;
5721 else
5722 return false;
5724 alloc_w_e3_arr_spec = true;
5727 /* Figure out the size of the array. */
5728 switch (ref->u.ar.type)
5730 case AR_ELEMENT:
5731 if (!coarray)
5733 lower = NULL;
5734 upper = ref->u.ar.start;
5735 break;
5737 /* Fall through. */
5739 case AR_SECTION:
5740 lower = ref->u.ar.start;
5741 upper = ref->u.ar.end;
5742 break;
5744 case AR_FULL:
5745 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT
5746 || alloc_w_e3_arr_spec);
5748 lower = ref->u.ar.as->lower;
5749 upper = ref->u.ar.as->upper;
5750 break;
5752 default:
5753 gcc_unreachable ();
5754 break;
5757 overflow = integer_zero_node;
5759 gfc_init_block (&set_descriptor_block);
5760 /* Take the corank only from the actual ref and not from the coref. The
5761 later will mislead the generation of the array dimensions for allocatable/
5762 pointer components in derived types. */
5763 size = gfc_array_init_size (se->expr, alloc_w_e3_arr_spec ? expr->rank
5764 : ref->u.ar.as->rank,
5765 coarray ? ref->u.ar.as->corank : 0,
5766 &offset, lower, upper,
5767 &se->pre, &set_descriptor_block, &overflow,
5768 expr3_elem_size, nelems, expr3, e3_arr_desc,
5769 e3_is_array_constr, expr);
5771 if (dimension)
5773 var_overflow = gfc_create_var (integer_type_node, "overflow");
5774 gfc_add_modify (&se->pre, var_overflow, overflow);
5776 if (status == NULL_TREE)
5778 /* Generate the block of code handling overflow. */
5779 msg = gfc_build_addr_expr (pchar_type_node,
5780 gfc_build_localized_cstring_const
5781 ("Integer overflow when calculating the amount of "
5782 "memory to allocate"));
5783 error = build_call_expr_loc (input_location,
5784 gfor_fndecl_runtime_error, 1, msg);
5786 else
5788 tree status_type = TREE_TYPE (status);
5789 stmtblock_t set_status_block;
5791 gfc_start_block (&set_status_block);
5792 gfc_add_modify (&set_status_block, status,
5793 build_int_cst (status_type, LIBERROR_ALLOCATION));
5794 error = gfc_finish_block (&set_status_block);
5798 gfc_start_block (&elseblock);
5800 /* Allocate memory to store the data. */
5801 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
5802 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
5804 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
5806 pointer = non_ulimate_coarray_ptr_comp ? se->expr
5807 : gfc_conv_descriptor_data_get (se->expr);
5808 token = gfc_conv_descriptor_token (se->expr);
5809 token = gfc_build_addr_expr (NULL_TREE, token);
5811 else
5812 pointer = gfc_conv_descriptor_data_get (se->expr);
5813 STRIP_NOPS (pointer);
5815 /* The allocatable variant takes the old pointer as first argument. */
5816 if (allocatable)
5817 gfc_allocate_allocatable (&elseblock, pointer, size, token,
5818 status, errmsg, errlen, label_finish, expr,
5819 coref != NULL ? coref->u.ar.as->corank : 0);
5820 else if (non_ulimate_coarray_ptr_comp && token)
5821 /* The token is set only for GFC_FCOARRAY_LIB mode. */
5822 gfc_allocate_using_caf_lib (&elseblock, pointer, size, token, status,
5823 errmsg, errlen,
5824 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY);
5825 else
5826 gfc_allocate_using_malloc (&elseblock, pointer, size, status);
5828 if (dimension)
5830 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
5831 logical_type_node, var_overflow, integer_zero_node),
5832 PRED_FORTRAN_OVERFLOW);
5833 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
5834 error, gfc_finish_block (&elseblock));
5836 else
5837 tmp = gfc_finish_block (&elseblock);
5839 gfc_add_expr_to_block (&se->pre, tmp);
5841 /* Update the array descriptors. */
5842 if (dimension)
5843 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
5845 /* Pointer arrays need the span field to be set. */
5846 if (is_pointer_array (se->expr)
5847 || (expr->ts.type == BT_CLASS
5848 && CLASS_DATA (expr)->attr.class_pointer))
5850 if (expr3 && expr3_elem_size != NULL_TREE)
5851 tmp = expr3_elem_size;
5852 else
5853 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (se->expr)));
5854 tmp = fold_convert (gfc_array_index_type, tmp);
5855 gfc_conv_descriptor_span_set (&set_descriptor_block, se->expr, tmp);
5858 set_descriptor = gfc_finish_block (&set_descriptor_block);
5859 if (status != NULL_TREE)
5861 cond = fold_build2_loc (input_location, EQ_EXPR,
5862 logical_type_node, status,
5863 build_int_cst (TREE_TYPE (status), 0));
5864 gfc_add_expr_to_block (&se->pre,
5865 fold_build3_loc (input_location, COND_EXPR, void_type_node,
5866 cond,
5867 set_descriptor,
5868 build_empty_stmt (input_location)));
5870 else
5871 gfc_add_expr_to_block (&se->pre, set_descriptor);
5873 return true;
5877 /* Create an array constructor from an initialization expression.
5878 We assume the frontend already did any expansions and conversions. */
5880 tree
5881 gfc_conv_array_initializer (tree type, gfc_expr * expr)
5883 gfc_constructor *c;
5884 tree tmp;
5885 offset_int wtmp;
5886 gfc_se se;
5887 tree index, range;
5888 vec<constructor_elt, va_gc> *v = NULL;
5890 if (expr->expr_type == EXPR_VARIABLE
5891 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
5892 && expr->symtree->n.sym->value)
5893 expr = expr->symtree->n.sym->value;
5895 switch (expr->expr_type)
5897 case EXPR_CONSTANT:
5898 case EXPR_STRUCTURE:
5899 /* A single scalar or derived type value. Create an array with all
5900 elements equal to that value. */
5901 gfc_init_se (&se, NULL);
5903 if (expr->expr_type == EXPR_CONSTANT)
5904 gfc_conv_constant (&se, expr);
5905 else
5906 gfc_conv_structure (&se, expr, 1);
5908 wtmp = wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1;
5909 /* This will probably eat buckets of memory for large arrays. */
5910 while (wtmp != 0)
5912 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
5913 wtmp -= 1;
5915 break;
5917 case EXPR_ARRAY:
5918 /* Create a vector of all the elements. */
5919 for (c = gfc_constructor_first (expr->value.constructor);
5920 c; c = gfc_constructor_next (c))
5922 if (c->iterator)
5924 /* Problems occur when we get something like
5925 integer :: a(lots) = (/(i, i=1, lots)/) */
5926 gfc_fatal_error ("The number of elements in the array "
5927 "constructor at %L requires an increase of "
5928 "the allowed %d upper limit. See "
5929 "%<-fmax-array-constructor%> option",
5930 &expr->where, flag_max_array_constructor);
5931 return NULL_TREE;
5933 if (mpz_cmp_si (c->offset, 0) != 0)
5934 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5935 else
5936 index = NULL_TREE;
5938 if (mpz_cmp_si (c->repeat, 1) > 0)
5940 tree tmp1, tmp2;
5941 mpz_t maxval;
5943 mpz_init (maxval);
5944 mpz_add (maxval, c->offset, c->repeat);
5945 mpz_sub_ui (maxval, maxval, 1);
5946 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5947 if (mpz_cmp_si (c->offset, 0) != 0)
5949 mpz_add_ui (maxval, c->offset, 1);
5950 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5952 else
5953 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5955 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
5956 mpz_clear (maxval);
5958 else
5959 range = NULL;
5961 gfc_init_se (&se, NULL);
5962 switch (c->expr->expr_type)
5964 case EXPR_CONSTANT:
5965 gfc_conv_constant (&se, c->expr);
5966 break;
5968 case EXPR_STRUCTURE:
5969 gfc_conv_structure (&se, c->expr, 1);
5970 break;
5972 default:
5973 /* Catch those occasional beasts that do not simplify
5974 for one reason or another, assuming that if they are
5975 standard defying the frontend will catch them. */
5976 gfc_conv_expr (&se, c->expr);
5977 break;
5980 if (range == NULL_TREE)
5981 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5982 else
5984 if (index != NULL_TREE)
5985 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5986 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
5989 break;
5991 case EXPR_NULL:
5992 return gfc_build_null_descriptor (type);
5994 default:
5995 gcc_unreachable ();
5998 /* Create a constructor from the list of elements. */
5999 tmp = build_constructor (type, v);
6000 TREE_CONSTANT (tmp) = 1;
6001 return tmp;
6005 /* Generate code to evaluate non-constant coarray cobounds. */
6007 void
6008 gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
6009 const gfc_symbol *sym)
6011 int dim;
6012 tree ubound;
6013 tree lbound;
6014 gfc_se se;
6015 gfc_array_spec *as;
6017 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6019 for (dim = as->rank; dim < as->rank + as->corank; dim++)
6021 /* Evaluate non-constant array bound expressions. */
6022 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6023 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6025 gfc_init_se (&se, NULL);
6026 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6027 gfc_add_block_to_block (pblock, &se.pre);
6028 gfc_add_modify (pblock, lbound, se.expr);
6030 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6031 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6033 gfc_init_se (&se, NULL);
6034 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6035 gfc_add_block_to_block (pblock, &se.pre);
6036 gfc_add_modify (pblock, ubound, se.expr);
6042 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
6043 returns the size (in elements) of the array. */
6045 static tree
6046 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
6047 stmtblock_t * pblock)
6049 gfc_array_spec *as;
6050 tree size;
6051 tree stride;
6052 tree offset;
6053 tree ubound;
6054 tree lbound;
6055 tree tmp;
6056 gfc_se se;
6058 int dim;
6060 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6062 size = gfc_index_one_node;
6063 offset = gfc_index_zero_node;
6064 for (dim = 0; dim < as->rank; dim++)
6066 /* Evaluate non-constant array bound expressions. */
6067 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6068 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6070 gfc_init_se (&se, NULL);
6071 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6072 gfc_add_block_to_block (pblock, &se.pre);
6073 gfc_add_modify (pblock, lbound, se.expr);
6075 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6076 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6078 gfc_init_se (&se, NULL);
6079 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6080 gfc_add_block_to_block (pblock, &se.pre);
6081 gfc_add_modify (pblock, ubound, se.expr);
6083 /* The offset of this dimension. offset = offset - lbound * stride. */
6084 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6085 lbound, size);
6086 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6087 offset, tmp);
6089 /* The size of this dimension, and the stride of the next. */
6090 if (dim + 1 < as->rank)
6091 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
6092 else
6093 stride = GFC_TYPE_ARRAY_SIZE (type);
6095 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
6097 /* Calculate stride = size * (ubound + 1 - lbound). */
6098 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6099 gfc_array_index_type,
6100 gfc_index_one_node, lbound);
6101 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6102 gfc_array_index_type, ubound, tmp);
6103 tmp = fold_build2_loc (input_location, MULT_EXPR,
6104 gfc_array_index_type, size, tmp);
6105 if (stride)
6106 gfc_add_modify (pblock, stride, tmp);
6107 else
6108 stride = gfc_evaluate_now (tmp, pblock);
6110 /* Make sure that negative size arrays are translated
6111 to being zero size. */
6112 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6113 stride, gfc_index_zero_node);
6114 tmp = fold_build3_loc (input_location, COND_EXPR,
6115 gfc_array_index_type, tmp,
6116 stride, gfc_index_zero_node);
6117 gfc_add_modify (pblock, stride, tmp);
6120 size = stride;
6123 gfc_trans_array_cobounds (type, pblock, sym);
6124 gfc_trans_vla_type_sizes (sym, pblock);
6126 *poffset = offset;
6127 return size;
6131 /* Generate code to initialize/allocate an array variable. */
6133 void
6134 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
6135 gfc_wrapped_block * block)
6137 stmtblock_t init;
6138 tree type;
6139 tree tmp = NULL_TREE;
6140 tree size;
6141 tree offset;
6142 tree space;
6143 tree inittree;
6144 bool onstack;
6146 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
6148 /* Do nothing for USEd variables. */
6149 if (sym->attr.use_assoc)
6150 return;
6152 type = TREE_TYPE (decl);
6153 gcc_assert (GFC_ARRAY_TYPE_P (type));
6154 onstack = TREE_CODE (type) != POINTER_TYPE;
6156 gfc_init_block (&init);
6158 /* Evaluate character string length. */
6159 if (sym->ts.type == BT_CHARACTER
6160 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6162 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6164 gfc_trans_vla_type_sizes (sym, &init);
6166 /* Emit a DECL_EXPR for this variable, which will cause the
6167 gimplifier to allocate storage, and all that good stuff. */
6168 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
6169 gfc_add_expr_to_block (&init, tmp);
6172 if (onstack)
6174 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6175 return;
6178 type = TREE_TYPE (type);
6180 gcc_assert (!sym->attr.use_assoc);
6181 gcc_assert (!TREE_STATIC (decl));
6182 gcc_assert (!sym->module);
6184 if (sym->ts.type == BT_CHARACTER
6185 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6186 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6188 size = gfc_trans_array_bounds (type, sym, &offset, &init);
6190 /* Don't actually allocate space for Cray Pointees. */
6191 if (sym->attr.cray_pointee)
6193 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6194 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6196 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6197 return;
6200 if (flag_stack_arrays)
6202 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
6203 space = build_decl (sym->declared_at.lb->location,
6204 VAR_DECL, create_tmp_var_name ("A"),
6205 TREE_TYPE (TREE_TYPE (decl)));
6206 gfc_trans_vla_type_sizes (sym, &init);
6208 else
6210 /* The size is the number of elements in the array, so multiply by the
6211 size of an element to get the total size. */
6212 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
6213 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6214 size, fold_convert (gfc_array_index_type, tmp));
6216 /* Allocate memory to hold the data. */
6217 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
6218 gfc_add_modify (&init, decl, tmp);
6220 /* Free the temporary. */
6221 tmp = gfc_call_free (decl);
6222 space = NULL_TREE;
6225 /* Set offset of the array. */
6226 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6227 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6229 /* Automatic arrays should not have initializers. */
6230 gcc_assert (!sym->value);
6232 inittree = gfc_finish_block (&init);
6234 if (space)
6236 tree addr;
6237 pushdecl (space);
6239 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
6240 where also space is located. */
6241 gfc_init_block (&init);
6242 tmp = fold_build1_loc (input_location, DECL_EXPR,
6243 TREE_TYPE (space), space);
6244 gfc_add_expr_to_block (&init, tmp);
6245 addr = fold_build1_loc (sym->declared_at.lb->location,
6246 ADDR_EXPR, TREE_TYPE (decl), space);
6247 gfc_add_modify (&init, decl, addr);
6248 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6249 tmp = NULL_TREE;
6251 gfc_add_init_cleanup (block, inittree, tmp);
6255 /* Generate entry and exit code for g77 calling convention arrays. */
6257 void
6258 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
6260 tree parm;
6261 tree type;
6262 locus loc;
6263 tree offset;
6264 tree tmp;
6265 tree stmt;
6266 stmtblock_t init;
6268 gfc_save_backend_locus (&loc);
6269 gfc_set_backend_locus (&sym->declared_at);
6271 /* Descriptor type. */
6272 parm = sym->backend_decl;
6273 type = TREE_TYPE (parm);
6274 gcc_assert (GFC_ARRAY_TYPE_P (type));
6276 gfc_start_block (&init);
6278 if (sym->ts.type == BT_CHARACTER
6279 && VAR_P (sym->ts.u.cl->backend_decl))
6280 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6282 /* Evaluate the bounds of the array. */
6283 gfc_trans_array_bounds (type, sym, &offset, &init);
6285 /* Set the offset. */
6286 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6287 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6289 /* Set the pointer itself if we aren't using the parameter directly. */
6290 if (TREE_CODE (parm) != PARM_DECL)
6292 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
6293 gfc_add_modify (&init, parm, tmp);
6295 stmt = gfc_finish_block (&init);
6297 gfc_restore_backend_locus (&loc);
6299 /* Add the initialization code to the start of the function. */
6301 if (sym->attr.optional || sym->attr.not_always_present)
6303 tmp = gfc_conv_expr_present (sym);
6304 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
6307 gfc_add_init_cleanup (block, stmt, NULL_TREE);
6311 /* Modify the descriptor of an array parameter so that it has the
6312 correct lower bound. Also move the upper bound accordingly.
6313 If the array is not packed, it will be copied into a temporary.
6314 For each dimension we set the new lower and upper bounds. Then we copy the
6315 stride and calculate the offset for this dimension. We also work out
6316 what the stride of a packed array would be, and see it the two match.
6317 If the array need repacking, we set the stride to the values we just
6318 calculated, recalculate the offset and copy the array data.
6319 Code is also added to copy the data back at the end of the function.
6322 void
6323 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
6324 gfc_wrapped_block * block)
6326 tree size;
6327 tree type;
6328 tree offset;
6329 locus loc;
6330 stmtblock_t init;
6331 tree stmtInit, stmtCleanup;
6332 tree lbound;
6333 tree ubound;
6334 tree dubound;
6335 tree dlbound;
6336 tree dumdesc;
6337 tree tmp;
6338 tree stride, stride2;
6339 tree stmt_packed;
6340 tree stmt_unpacked;
6341 tree partial;
6342 gfc_se se;
6343 int n;
6344 int checkparm;
6345 int no_repack;
6346 bool optional_arg;
6347 gfc_array_spec *as;
6348 bool is_classarray = IS_CLASS_ARRAY (sym);
6350 /* Do nothing for pointer and allocatable arrays. */
6351 if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
6352 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
6353 || sym->attr.allocatable
6354 || (is_classarray && CLASS_DATA (sym)->attr.allocatable))
6355 return;
6357 if (!is_classarray && sym->attr.dummy && gfc_is_nodesc_array (sym))
6359 gfc_trans_g77_array (sym, block);
6360 return;
6363 loc.nextc = NULL;
6364 gfc_save_backend_locus (&loc);
6365 /* loc.nextc is not set by save_backend_locus but the location routines
6366 depend on it. */
6367 if (loc.nextc == NULL)
6368 loc.nextc = loc.lb->line;
6369 gfc_set_backend_locus (&sym->declared_at);
6371 /* Descriptor type. */
6372 type = TREE_TYPE (tmpdesc);
6373 gcc_assert (GFC_ARRAY_TYPE_P (type));
6374 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6375 if (is_classarray)
6376 /* For a class array the dummy array descriptor is in the _class
6377 component. */
6378 dumdesc = gfc_class_data_get (dumdesc);
6379 else
6380 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
6381 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6382 gfc_start_block (&init);
6384 if (sym->ts.type == BT_CHARACTER
6385 && VAR_P (sym->ts.u.cl->backend_decl))
6386 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6388 checkparm = (as->type == AS_EXPLICIT
6389 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
6391 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
6392 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
6394 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
6396 /* For non-constant shape arrays we only check if the first dimension
6397 is contiguous. Repacking higher dimensions wouldn't gain us
6398 anything as we still don't know the array stride. */
6399 partial = gfc_create_var (logical_type_node, "partial");
6400 TREE_USED (partial) = 1;
6401 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
6402 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
6403 gfc_index_one_node);
6404 gfc_add_modify (&init, partial, tmp);
6406 else
6407 partial = NULL_TREE;
6409 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
6410 here, however I think it does the right thing. */
6411 if (no_repack)
6413 /* Set the first stride. */
6414 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
6415 stride = gfc_evaluate_now (stride, &init);
6417 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6418 stride, gfc_index_zero_node);
6419 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
6420 tmp, gfc_index_one_node, stride);
6421 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
6422 gfc_add_modify (&init, stride, tmp);
6424 /* Allow the user to disable array repacking. */
6425 stmt_unpacked = NULL_TREE;
6427 else
6429 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
6430 /* A library call to repack the array if necessary. */
6431 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6432 stmt_unpacked = build_call_expr_loc (input_location,
6433 gfor_fndecl_in_pack, 1, tmp);
6435 stride = gfc_index_one_node;
6437 if (warn_array_temporaries)
6438 gfc_warning (OPT_Warray_temporaries,
6439 "Creating array temporary at %L", &loc);
6442 /* This is for the case where the array data is used directly without
6443 calling the repack function. */
6444 if (no_repack || partial != NULL_TREE)
6445 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
6446 else
6447 stmt_packed = NULL_TREE;
6449 /* Assign the data pointer. */
6450 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6452 /* Don't repack unknown shape arrays when the first stride is 1. */
6453 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
6454 partial, stmt_packed, stmt_unpacked);
6456 else
6457 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
6458 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
6460 offset = gfc_index_zero_node;
6461 size = gfc_index_one_node;
6463 /* Evaluate the bounds of the array. */
6464 for (n = 0; n < as->rank; n++)
6466 if (checkparm || !as->upper[n])
6468 /* Get the bounds of the actual parameter. */
6469 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
6470 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
6472 else
6474 dubound = NULL_TREE;
6475 dlbound = NULL_TREE;
6478 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
6479 if (!INTEGER_CST_P (lbound))
6481 gfc_init_se (&se, NULL);
6482 gfc_conv_expr_type (&se, as->lower[n],
6483 gfc_array_index_type);
6484 gfc_add_block_to_block (&init, &se.pre);
6485 gfc_add_modify (&init, lbound, se.expr);
6488 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
6489 /* Set the desired upper bound. */
6490 if (as->upper[n])
6492 /* We know what we want the upper bound to be. */
6493 if (!INTEGER_CST_P (ubound))
6495 gfc_init_se (&se, NULL);
6496 gfc_conv_expr_type (&se, as->upper[n],
6497 gfc_array_index_type);
6498 gfc_add_block_to_block (&init, &se.pre);
6499 gfc_add_modify (&init, ubound, se.expr);
6502 /* Check the sizes match. */
6503 if (checkparm)
6505 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
6506 char * msg;
6507 tree temp;
6509 temp = fold_build2_loc (input_location, MINUS_EXPR,
6510 gfc_array_index_type, ubound, lbound);
6511 temp = fold_build2_loc (input_location, PLUS_EXPR,
6512 gfc_array_index_type,
6513 gfc_index_one_node, temp);
6514 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
6515 gfc_array_index_type, dubound,
6516 dlbound);
6517 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
6518 gfc_array_index_type,
6519 gfc_index_one_node, stride2);
6520 tmp = fold_build2_loc (input_location, NE_EXPR,
6521 gfc_array_index_type, temp, stride2);
6522 msg = xasprintf ("Dimension %d of array '%s' has extent "
6523 "%%ld instead of %%ld", n+1, sym->name);
6525 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
6526 fold_convert (long_integer_type_node, temp),
6527 fold_convert (long_integer_type_node, stride2));
6529 free (msg);
6532 else
6534 /* For assumed shape arrays move the upper bound by the same amount
6535 as the lower bound. */
6536 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6537 gfc_array_index_type, dubound, dlbound);
6538 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6539 gfc_array_index_type, tmp, lbound);
6540 gfc_add_modify (&init, ubound, tmp);
6542 /* The offset of this dimension. offset = offset - lbound * stride. */
6543 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6544 lbound, stride);
6545 offset = fold_build2_loc (input_location, MINUS_EXPR,
6546 gfc_array_index_type, offset, tmp);
6548 /* The size of this dimension, and the stride of the next. */
6549 if (n + 1 < as->rank)
6551 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
6553 if (no_repack || partial != NULL_TREE)
6554 stmt_unpacked =
6555 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
6557 /* Figure out the stride if not a known constant. */
6558 if (!INTEGER_CST_P (stride))
6560 if (no_repack)
6561 stmt_packed = NULL_TREE;
6562 else
6564 /* Calculate stride = size * (ubound + 1 - lbound). */
6565 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6566 gfc_array_index_type,
6567 gfc_index_one_node, lbound);
6568 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6569 gfc_array_index_type, ubound, tmp);
6570 size = fold_build2_loc (input_location, MULT_EXPR,
6571 gfc_array_index_type, size, tmp);
6572 stmt_packed = size;
6575 /* Assign the stride. */
6576 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6577 tmp = fold_build3_loc (input_location, COND_EXPR,
6578 gfc_array_index_type, partial,
6579 stmt_unpacked, stmt_packed);
6580 else
6581 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
6582 gfc_add_modify (&init, stride, tmp);
6585 else
6587 stride = GFC_TYPE_ARRAY_SIZE (type);
6589 if (stride && !INTEGER_CST_P (stride))
6591 /* Calculate size = stride * (ubound + 1 - lbound). */
6592 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6593 gfc_array_index_type,
6594 gfc_index_one_node, lbound);
6595 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6596 gfc_array_index_type,
6597 ubound, tmp);
6598 tmp = fold_build2_loc (input_location, MULT_EXPR,
6599 gfc_array_index_type,
6600 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
6601 gfc_add_modify (&init, stride, tmp);
6606 gfc_trans_array_cobounds (type, &init, sym);
6608 /* Set the offset. */
6609 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6610 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6612 gfc_trans_vla_type_sizes (sym, &init);
6614 stmtInit = gfc_finish_block (&init);
6616 /* Only do the entry/initialization code if the arg is present. */
6617 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6618 optional_arg = (sym->attr.optional
6619 || (sym->ns->proc_name->attr.entry_master
6620 && sym->attr.dummy));
6621 if (optional_arg)
6623 tmp = gfc_conv_expr_present (sym);
6624 stmtInit = build3_v (COND_EXPR, tmp, stmtInit,
6625 build_empty_stmt (input_location));
6628 /* Cleanup code. */
6629 if (no_repack)
6630 stmtCleanup = NULL_TREE;
6631 else
6633 stmtblock_t cleanup;
6634 gfc_start_block (&cleanup);
6636 if (sym->attr.intent != INTENT_IN)
6638 /* Copy the data back. */
6639 tmp = build_call_expr_loc (input_location,
6640 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
6641 gfc_add_expr_to_block (&cleanup, tmp);
6644 /* Free the temporary. */
6645 tmp = gfc_call_free (tmpdesc);
6646 gfc_add_expr_to_block (&cleanup, tmp);
6648 stmtCleanup = gfc_finish_block (&cleanup);
6650 /* Only do the cleanup if the array was repacked. */
6651 if (is_classarray)
6652 /* For a class array the dummy array descriptor is in the _class
6653 component. */
6654 tmp = gfc_class_data_get (dumdesc);
6655 else
6656 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
6657 tmp = gfc_conv_descriptor_data_get (tmp);
6658 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6659 tmp, tmpdesc);
6660 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6661 build_empty_stmt (input_location));
6663 if (optional_arg)
6665 tmp = gfc_conv_expr_present (sym);
6666 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6667 build_empty_stmt (input_location));
6671 /* We don't need to free any memory allocated by internal_pack as it will
6672 be freed at the end of the function by pop_context. */
6673 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
6675 gfc_restore_backend_locus (&loc);
6679 /* Calculate the overall offset, including subreferences. */
6680 static void
6681 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
6682 bool subref, gfc_expr *expr)
6684 tree tmp;
6685 tree field;
6686 tree stride;
6687 tree index;
6688 gfc_ref *ref;
6689 gfc_se start;
6690 int n;
6692 /* If offset is NULL and this is not a subreferenced array, there is
6693 nothing to do. */
6694 if (offset == NULL_TREE)
6696 if (subref)
6697 offset = gfc_index_zero_node;
6698 else
6699 return;
6702 tmp = build_array_ref (desc, offset, NULL, NULL);
6704 /* Offset the data pointer for pointer assignments from arrays with
6705 subreferences; e.g. my_integer => my_type(:)%integer_component. */
6706 if (subref)
6708 /* Go past the array reference. */
6709 for (ref = expr->ref; ref; ref = ref->next)
6710 if (ref->type == REF_ARRAY &&
6711 ref->u.ar.type != AR_ELEMENT)
6713 ref = ref->next;
6714 break;
6717 /* Calculate the offset for each subsequent subreference. */
6718 for (; ref; ref = ref->next)
6720 switch (ref->type)
6722 case REF_COMPONENT:
6723 field = ref->u.c.component->backend_decl;
6724 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6725 tmp = fold_build3_loc (input_location, COMPONENT_REF,
6726 TREE_TYPE (field),
6727 tmp, field, NULL_TREE);
6728 break;
6730 case REF_SUBSTRING:
6731 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
6732 gfc_init_se (&start, NULL);
6733 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
6734 gfc_add_block_to_block (block, &start.pre);
6735 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
6736 break;
6738 case REF_ARRAY:
6739 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
6740 && ref->u.ar.type == AR_ELEMENT);
6742 /* TODO - Add bounds checking. */
6743 stride = gfc_index_one_node;
6744 index = gfc_index_zero_node;
6745 for (n = 0; n < ref->u.ar.dimen; n++)
6747 tree itmp;
6748 tree jtmp;
6750 /* Update the index. */
6751 gfc_init_se (&start, NULL);
6752 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
6753 itmp = gfc_evaluate_now (start.expr, block);
6754 gfc_init_se (&start, NULL);
6755 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
6756 jtmp = gfc_evaluate_now (start.expr, block);
6757 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6758 gfc_array_index_type, itmp, jtmp);
6759 itmp = fold_build2_loc (input_location, MULT_EXPR,
6760 gfc_array_index_type, itmp, stride);
6761 index = fold_build2_loc (input_location, PLUS_EXPR,
6762 gfc_array_index_type, itmp, index);
6763 index = gfc_evaluate_now (index, block);
6765 /* Update the stride. */
6766 gfc_init_se (&start, NULL);
6767 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
6768 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6769 gfc_array_index_type, start.expr,
6770 jtmp);
6771 itmp = fold_build2_loc (input_location, PLUS_EXPR,
6772 gfc_array_index_type,
6773 gfc_index_one_node, itmp);
6774 stride = fold_build2_loc (input_location, MULT_EXPR,
6775 gfc_array_index_type, stride, itmp);
6776 stride = gfc_evaluate_now (stride, block);
6779 /* Apply the index to obtain the array element. */
6780 tmp = gfc_build_array_ref (tmp, index, NULL);
6781 break;
6783 default:
6784 gcc_unreachable ();
6785 break;
6790 /* Set the target data pointer. */
6791 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
6792 gfc_conv_descriptor_data_set (block, parm, offset);
6796 /* gfc_conv_expr_descriptor needs the string length an expression
6797 so that the size of the temporary can be obtained. This is done
6798 by adding up the string lengths of all the elements in the
6799 expression. Function with non-constant expressions have their
6800 string lengths mapped onto the actual arguments using the
6801 interface mapping machinery in trans-expr.c. */
6802 static void
6803 get_array_charlen (gfc_expr *expr, gfc_se *se)
6805 gfc_interface_mapping mapping;
6806 gfc_formal_arglist *formal;
6807 gfc_actual_arglist *arg;
6808 gfc_se tse;
6810 if (expr->ts.u.cl->length
6811 && gfc_is_constant_expr (expr->ts.u.cl->length))
6813 if (!expr->ts.u.cl->backend_decl)
6814 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6815 return;
6818 switch (expr->expr_type)
6820 case EXPR_OP:
6821 get_array_charlen (expr->value.op.op1, se);
6823 /* For parentheses the expression ts.u.cl is identical. */
6824 if (expr->value.op.op == INTRINSIC_PARENTHESES)
6825 return;
6827 expr->ts.u.cl->backend_decl =
6828 gfc_create_var (gfc_charlen_type_node, "sln");
6830 if (expr->value.op.op2)
6832 get_array_charlen (expr->value.op.op2, se);
6834 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
6836 /* Add the string lengths and assign them to the expression
6837 string length backend declaration. */
6838 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6839 fold_build2_loc (input_location, PLUS_EXPR,
6840 gfc_charlen_type_node,
6841 expr->value.op.op1->ts.u.cl->backend_decl,
6842 expr->value.op.op2->ts.u.cl->backend_decl));
6844 else
6845 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6846 expr->value.op.op1->ts.u.cl->backend_decl);
6847 break;
6849 case EXPR_FUNCTION:
6850 if (expr->value.function.esym == NULL
6851 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
6853 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6854 break;
6857 /* Map expressions involving the dummy arguments onto the actual
6858 argument expressions. */
6859 gfc_init_interface_mapping (&mapping);
6860 formal = gfc_sym_get_dummy_args (expr->symtree->n.sym);
6861 arg = expr->value.function.actual;
6863 /* Set se = NULL in the calls to the interface mapping, to suppress any
6864 backend stuff. */
6865 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
6867 if (!arg->expr)
6868 continue;
6869 if (formal->sym)
6870 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
6873 gfc_init_se (&tse, NULL);
6875 /* Build the expression for the character length and convert it. */
6876 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
6878 gfc_add_block_to_block (&se->pre, &tse.pre);
6879 gfc_add_block_to_block (&se->post, &tse.post);
6880 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
6881 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
6882 TREE_TYPE (tse.expr), tse.expr,
6883 build_zero_cst (TREE_TYPE (tse.expr)));
6884 expr->ts.u.cl->backend_decl = tse.expr;
6885 gfc_free_interface_mapping (&mapping);
6886 break;
6888 default:
6889 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6890 break;
6895 /* Helper function to check dimensions. */
6896 static bool
6897 transposed_dims (gfc_ss *ss)
6899 int n;
6901 for (n = 0; n < ss->dimen; n++)
6902 if (ss->dim[n] != n)
6903 return true;
6904 return false;
6908 /* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
6909 AR_FULL, suitable for the scalarizer. */
6911 static gfc_ss *
6912 walk_coarray (gfc_expr *e)
6914 gfc_ss *ss;
6916 gcc_assert (gfc_get_corank (e) > 0);
6918 ss = gfc_walk_expr (e);
6920 /* Fix scalar coarray. */
6921 if (ss == gfc_ss_terminator)
6923 gfc_ref *ref;
6925 ref = e->ref;
6926 while (ref)
6928 if (ref->type == REF_ARRAY
6929 && ref->u.ar.codimen > 0)
6930 break;
6932 ref = ref->next;
6935 gcc_assert (ref != NULL);
6936 if (ref->u.ar.type == AR_ELEMENT)
6937 ref->u.ar.type = AR_SECTION;
6938 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
6941 return ss;
6945 /* Convert an array for passing as an actual argument. Expressions and
6946 vector subscripts are evaluated and stored in a temporary, which is then
6947 passed. For whole arrays the descriptor is passed. For array sections
6948 a modified copy of the descriptor is passed, but using the original data.
6950 This function is also used for array pointer assignments, and there
6951 are three cases:
6953 - se->want_pointer && !se->direct_byref
6954 EXPR is an actual argument. On exit, se->expr contains a
6955 pointer to the array descriptor.
6957 - !se->want_pointer && !se->direct_byref
6958 EXPR is an actual argument to an intrinsic function or the
6959 left-hand side of a pointer assignment. On exit, se->expr
6960 contains the descriptor for EXPR.
6962 - !se->want_pointer && se->direct_byref
6963 EXPR is the right-hand side of a pointer assignment and
6964 se->expr is the descriptor for the previously-evaluated
6965 left-hand side. The function creates an assignment from
6966 EXPR to se->expr.
6969 The se->force_tmp flag disables the non-copying descriptor optimization
6970 that is used for transpose. It may be used in cases where there is an
6971 alias between the transpose argument and another argument in the same
6972 function call. */
6974 void
6975 gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
6977 gfc_ss *ss;
6978 gfc_ss_type ss_type;
6979 gfc_ss_info *ss_info;
6980 gfc_loopinfo loop;
6981 gfc_array_info *info;
6982 int need_tmp;
6983 int n;
6984 tree tmp;
6985 tree desc;
6986 stmtblock_t block;
6987 tree start;
6988 tree offset;
6989 int full;
6990 bool subref_array_target = false;
6991 gfc_expr *arg, *ss_expr;
6993 if (se->want_coarray)
6994 ss = walk_coarray (expr);
6995 else
6996 ss = gfc_walk_expr (expr);
6998 gcc_assert (ss != NULL);
6999 gcc_assert (ss != gfc_ss_terminator);
7001 ss_info = ss->info;
7002 ss_type = ss_info->type;
7003 ss_expr = ss_info->expr;
7005 /* Special case: TRANSPOSE which needs no temporary. */
7006 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
7007 && (arg = gfc_get_noncopying_intrinsic_argument (expr)) != NULL)
7009 /* This is a call to transpose which has already been handled by the
7010 scalarizer, so that we just need to get its argument's descriptor. */
7011 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
7012 expr = expr->value.function.actual->expr;
7015 /* Special case things we know we can pass easily. */
7016 switch (expr->expr_type)
7018 case EXPR_VARIABLE:
7019 /* If we have a linear array section, we can pass it directly.
7020 Otherwise we need to copy it into a temporary. */
7022 gcc_assert (ss_type == GFC_SS_SECTION);
7023 gcc_assert (ss_expr == expr);
7024 info = &ss_info->data.array;
7026 /* Get the descriptor for the array. */
7027 gfc_conv_ss_descriptor (&se->pre, ss, 0);
7028 desc = info->descriptor;
7030 subref_array_target = se->direct_byref && is_subref_array (expr);
7031 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
7032 && !subref_array_target;
7034 if (se->force_tmp)
7035 need_tmp = 1;
7037 if (need_tmp)
7038 full = 0;
7039 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7041 /* Create a new descriptor if the array doesn't have one. */
7042 full = 0;
7044 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
7045 full = 1;
7046 else if (se->direct_byref)
7047 full = 0;
7048 else
7049 full = gfc_full_array_ref_p (info->ref, NULL);
7051 if (full && !transposed_dims (ss))
7053 if (se->direct_byref && !se->byref_noassign)
7055 /* Copy the descriptor for pointer assignments. */
7056 gfc_add_modify (&se->pre, se->expr, desc);
7058 /* Add any offsets from subreferences. */
7059 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
7060 subref_array_target, expr);
7062 /* ....and set the span field. */
7063 tmp = get_array_span (desc, expr);
7064 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7066 else if (se->want_pointer)
7068 /* We pass full arrays directly. This means that pointers and
7069 allocatable arrays should also work. */
7070 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7072 else
7074 se->expr = desc;
7077 if (expr->ts.type == BT_CHARACTER)
7078 se->string_length = gfc_get_expr_charlen (expr);
7080 gfc_free_ss_chain (ss);
7081 return;
7083 break;
7085 case EXPR_FUNCTION:
7086 /* A transformational function return value will be a temporary
7087 array descriptor. We still need to go through the scalarizer
7088 to create the descriptor. Elemental functions are handled as
7089 arbitrary expressions, i.e. copy to a temporary. */
7091 if (se->direct_byref)
7093 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
7095 /* For pointer assignments pass the descriptor directly. */
7096 if (se->ss == NULL)
7097 se->ss = ss;
7098 else
7099 gcc_assert (se->ss == ss);
7101 if (!is_pointer_array (se->expr))
7103 tmp = gfc_get_element_type (TREE_TYPE (se->expr));
7104 tmp = fold_convert (gfc_array_index_type,
7105 size_in_bytes (tmp));
7106 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7109 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7110 gfc_conv_expr (se, expr);
7112 gfc_free_ss_chain (ss);
7113 return;
7116 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
7118 if (ss_expr != expr)
7119 /* Elemental function. */
7120 gcc_assert ((expr->value.function.esym != NULL
7121 && expr->value.function.esym->attr.elemental)
7122 || (expr->value.function.isym != NULL
7123 && expr->value.function.isym->elemental)
7124 || gfc_inline_intrinsic_function_p (expr));
7125 else
7126 gcc_assert (ss_type == GFC_SS_INTRINSIC);
7128 need_tmp = 1;
7129 if (expr->ts.type == BT_CHARACTER
7130 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
7131 get_array_charlen (expr, se);
7133 info = NULL;
7135 else
7137 /* Transformational function. */
7138 info = &ss_info->data.array;
7139 need_tmp = 0;
7141 break;
7143 case EXPR_ARRAY:
7144 /* Constant array constructors don't need a temporary. */
7145 if (ss_type == GFC_SS_CONSTRUCTOR
7146 && expr->ts.type != BT_CHARACTER
7147 && gfc_constant_array_constructor_p (expr->value.constructor))
7149 need_tmp = 0;
7150 info = &ss_info->data.array;
7152 else
7154 need_tmp = 1;
7155 info = NULL;
7157 break;
7159 default:
7160 /* Something complicated. Copy it into a temporary. */
7161 need_tmp = 1;
7162 info = NULL;
7163 break;
7166 /* If we are creating a temporary, we don't need to bother about aliases
7167 anymore. */
7168 if (need_tmp)
7169 se->force_tmp = 0;
7171 gfc_init_loopinfo (&loop);
7173 /* Associate the SS with the loop. */
7174 gfc_add_ss_to_loop (&loop, ss);
7176 /* Tell the scalarizer not to bother creating loop variables, etc. */
7177 if (!need_tmp)
7178 loop.array_parameter = 1;
7179 else
7180 /* The right-hand side of a pointer assignment mustn't use a temporary. */
7181 gcc_assert (!se->direct_byref);
7183 /* Setup the scalarizing loops and bounds. */
7184 gfc_conv_ss_startstride (&loop);
7186 if (need_tmp)
7188 if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
7189 get_array_charlen (expr, se);
7191 /* Tell the scalarizer to make a temporary. */
7192 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
7193 ((expr->ts.type == BT_CHARACTER)
7194 ? expr->ts.u.cl->backend_decl
7195 : NULL),
7196 loop.dimen);
7198 se->string_length = loop.temp_ss->info->string_length;
7199 gcc_assert (loop.temp_ss->dimen == loop.dimen);
7200 gfc_add_ss_to_loop (&loop, loop.temp_ss);
7203 gfc_conv_loop_setup (&loop, & expr->where);
7205 if (need_tmp)
7207 /* Copy into a temporary and pass that. We don't need to copy the data
7208 back because expressions and vector subscripts must be INTENT_IN. */
7209 /* TODO: Optimize passing function return values. */
7210 gfc_se lse;
7211 gfc_se rse;
7212 bool deep_copy;
7214 /* Start the copying loops. */
7215 gfc_mark_ss_chain_used (loop.temp_ss, 1);
7216 gfc_mark_ss_chain_used (ss, 1);
7217 gfc_start_scalarized_body (&loop, &block);
7219 /* Copy each data element. */
7220 gfc_init_se (&lse, NULL);
7221 gfc_copy_loopinfo_to_se (&lse, &loop);
7222 gfc_init_se (&rse, NULL);
7223 gfc_copy_loopinfo_to_se (&rse, &loop);
7225 lse.ss = loop.temp_ss;
7226 rse.ss = ss;
7228 gfc_conv_scalarized_array_ref (&lse, NULL);
7229 if (expr->ts.type == BT_CHARACTER)
7231 gfc_conv_expr (&rse, expr);
7232 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
7233 rse.expr = build_fold_indirect_ref_loc (input_location,
7234 rse.expr);
7236 else
7237 gfc_conv_expr_val (&rse, expr);
7239 gfc_add_block_to_block (&block, &rse.pre);
7240 gfc_add_block_to_block (&block, &lse.pre);
7242 lse.string_length = rse.string_length;
7244 deep_copy = !se->data_not_needed
7245 && (expr->expr_type == EXPR_VARIABLE
7246 || expr->expr_type == EXPR_ARRAY);
7247 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
7248 deep_copy, false);
7249 gfc_add_expr_to_block (&block, tmp);
7251 /* Finish the copying loops. */
7252 gfc_trans_scalarizing_loops (&loop, &block);
7254 desc = loop.temp_ss->info->data.array.descriptor;
7256 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
7258 desc = info->descriptor;
7259 se->string_length = ss_info->string_length;
7261 else
7263 /* We pass sections without copying to a temporary. Make a new
7264 descriptor and point it at the section we want. The loop variable
7265 limits will be the limits of the section.
7266 A function may decide to repack the array to speed up access, but
7267 we're not bothered about that here. */
7268 int dim, ndim, codim;
7269 tree parm;
7270 tree parmtype;
7271 tree stride;
7272 tree from;
7273 tree to;
7274 tree base;
7275 bool onebased = false, rank_remap;
7277 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
7278 rank_remap = ss->dimen < ndim;
7280 if (se->want_coarray)
7282 gfc_array_ref *ar = &info->ref->u.ar;
7284 codim = gfc_get_corank (expr);
7285 for (n = 0; n < codim - 1; n++)
7287 /* Make sure we are not lost somehow. */
7288 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
7290 /* Make sure the call to gfc_conv_section_startstride won't
7291 generate unnecessary code to calculate stride. */
7292 gcc_assert (ar->stride[n + ndim] == NULL);
7294 gfc_conv_section_startstride (&loop.pre, ss, n + ndim);
7295 loop.from[n + loop.dimen] = info->start[n + ndim];
7296 loop.to[n + loop.dimen] = info->end[n + ndim];
7299 gcc_assert (n == codim - 1);
7300 evaluate_bound (&loop.pre, info->start, ar->start,
7301 info->descriptor, n + ndim, true,
7302 ar->as->type == AS_DEFERRED);
7303 loop.from[n + loop.dimen] = info->start[n + ndim];
7305 else
7306 codim = 0;
7308 /* Set the string_length for a character array. */
7309 if (expr->ts.type == BT_CHARACTER)
7310 se->string_length = gfc_get_expr_charlen (expr);
7312 /* If we have an array section or are assigning make sure that
7313 the lower bound is 1. References to the full
7314 array should otherwise keep the original bounds. */
7315 if ((!info->ref || info->ref->u.ar.type != AR_FULL) && !se->want_pointer)
7316 for (dim = 0; dim < loop.dimen; dim++)
7317 if (!integer_onep (loop.from[dim]))
7319 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7320 gfc_array_index_type, gfc_index_one_node,
7321 loop.from[dim]);
7322 loop.to[dim] = fold_build2_loc (input_location, PLUS_EXPR,
7323 gfc_array_index_type,
7324 loop.to[dim], tmp);
7325 loop.from[dim] = gfc_index_one_node;
7328 desc = info->descriptor;
7329 if (se->direct_byref && !se->byref_noassign)
7331 /* For pointer assignments we fill in the destination.... */
7332 parm = se->expr;
7333 parmtype = TREE_TYPE (parm);
7335 /* ....and set the span field. */
7336 tmp = get_array_span (desc, expr);
7337 gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
7339 else
7341 /* Otherwise make a new one. */
7342 parmtype = gfc_get_element_type (TREE_TYPE (desc));
7343 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
7344 loop.from, loop.to, 0,
7345 GFC_ARRAY_UNKNOWN, false);
7346 parm = gfc_create_var (parmtype, "parm");
7348 /* When expression is a class object, then add the class' handle to
7349 the parm_decl. */
7350 if (expr->ts.type == BT_CLASS && expr->expr_type == EXPR_VARIABLE)
7352 gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (expr);
7353 gfc_se classse;
7355 /* class_expr can be NULL, when no _class ref is in expr.
7356 We must not fix this here with a gfc_fix_class_ref (). */
7357 if (class_expr)
7359 gfc_init_se (&classse, NULL);
7360 gfc_conv_expr (&classse, class_expr);
7361 gfc_free_expr (class_expr);
7363 gcc_assert (classse.pre.head == NULL_TREE
7364 && classse.post.head == NULL_TREE);
7365 gfc_allocate_lang_decl (parm);
7366 GFC_DECL_SAVED_DESCRIPTOR (parm) = classse.expr;
7371 offset = gfc_index_zero_node;
7373 /* The following can be somewhat confusing. We have two
7374 descriptors, a new one and the original array.
7375 {parm, parmtype, dim} refer to the new one.
7376 {desc, type, n, loop} refer to the original, which maybe
7377 a descriptorless array.
7378 The bounds of the scalarization are the bounds of the section.
7379 We don't have to worry about numeric overflows when calculating
7380 the offsets because all elements are within the array data. */
7382 /* Set the dtype. */
7383 tmp = gfc_conv_descriptor_dtype (parm);
7384 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
7386 /* Set offset for assignments to pointer only to zero if it is not
7387 the full array. */
7388 if ((se->direct_byref || se->use_offset)
7389 && ((info->ref && info->ref->u.ar.type != AR_FULL)
7390 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
7391 base = gfc_index_zero_node;
7392 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7393 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
7394 else
7395 base = NULL_TREE;
7397 for (n = 0; n < ndim; n++)
7399 stride = gfc_conv_array_stride (desc, n);
7401 /* Work out the offset. */
7402 if (info->ref
7403 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
7405 gcc_assert (info->subscript[n]
7406 && info->subscript[n]->info->type == GFC_SS_SCALAR);
7407 start = info->subscript[n]->info->data.scalar.value;
7409 else
7411 /* Evaluate and remember the start of the section. */
7412 start = info->start[n];
7413 stride = gfc_evaluate_now (stride, &loop.pre);
7416 tmp = gfc_conv_array_lbound (desc, n);
7417 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
7418 start, tmp);
7419 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
7420 tmp, stride);
7421 offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
7422 offset, tmp);
7424 if (info->ref
7425 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
7427 /* For elemental dimensions, we only need the offset. */
7428 continue;
7431 /* Vector subscripts need copying and are handled elsewhere. */
7432 if (info->ref)
7433 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
7435 /* look for the corresponding scalarizer dimension: dim. */
7436 for (dim = 0; dim < ndim; dim++)
7437 if (ss->dim[dim] == n)
7438 break;
7440 /* loop exited early: the DIM being looked for has been found. */
7441 gcc_assert (dim < ndim);
7443 /* Set the new lower bound. */
7444 from = loop.from[dim];
7445 to = loop.to[dim];
7447 onebased = integer_onep (from);
7448 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
7449 gfc_rank_cst[dim], from);
7451 /* Set the new upper bound. */
7452 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
7453 gfc_rank_cst[dim], to);
7455 /* Multiply the stride by the section stride to get the
7456 total stride. */
7457 stride = fold_build2_loc (input_location, MULT_EXPR,
7458 gfc_array_index_type,
7459 stride, info->stride[n]);
7461 if ((se->direct_byref || se->use_offset)
7462 && ((info->ref && info->ref->u.ar.type != AR_FULL)
7463 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
7465 base = fold_build2_loc (input_location, MINUS_EXPR,
7466 TREE_TYPE (base), base, stride);
7468 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)) || se->use_offset)
7470 bool toonebased;
7471 tmp = gfc_conv_array_lbound (desc, n);
7472 toonebased = integer_onep (tmp);
7473 // lb(arr) - from (- start + 1)
7474 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7475 TREE_TYPE (base), tmp, from);
7476 if (onebased && toonebased)
7478 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7479 TREE_TYPE (base), tmp, start);
7480 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7481 TREE_TYPE (base), tmp,
7482 gfc_index_one_node);
7484 tmp = fold_build2_loc (input_location, MULT_EXPR,
7485 TREE_TYPE (base), tmp,
7486 gfc_conv_array_stride (desc, n));
7487 base = fold_build2_loc (input_location, PLUS_EXPR,
7488 TREE_TYPE (base), tmp, base);
7491 /* Store the new stride. */
7492 gfc_conv_descriptor_stride_set (&loop.pre, parm,
7493 gfc_rank_cst[dim], stride);
7496 for (n = loop.dimen; n < loop.dimen + codim; n++)
7498 from = loop.from[n];
7499 to = loop.to[n];
7500 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
7501 gfc_rank_cst[n], from);
7502 if (n < loop.dimen + codim - 1)
7503 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
7504 gfc_rank_cst[n], to);
7507 if (se->data_not_needed)
7508 gfc_conv_descriptor_data_set (&loop.pre, parm,
7509 gfc_index_zero_node);
7510 else
7511 /* Point the data pointer at the 1st element in the section. */
7512 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
7513 subref_array_target, expr);
7515 /* Force the offset to be -1, when the lower bound of the highest
7516 dimension is one and the symbol is present and is not a
7517 pointer/allocatable or associated. */
7518 if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7519 && !se->data_not_needed)
7520 || (se->use_offset && base != NULL_TREE))
7522 /* Set the offset depending on base. */
7523 tmp = rank_remap && !se->direct_byref ?
7524 fold_build2_loc (input_location, PLUS_EXPR,
7525 gfc_array_index_type, base,
7526 offset)
7527 : base;
7528 gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
7530 else if (IS_CLASS_ARRAY (expr) && !se->data_not_needed
7531 && (!rank_remap || se->use_offset)
7532 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
7534 gfc_conv_descriptor_offset_set (&loop.pre, parm,
7535 gfc_conv_descriptor_offset_get (desc));
7537 else if (onebased && (!rank_remap || se->use_offset)
7538 && expr->symtree
7539 && !(expr->symtree->n.sym && expr->symtree->n.sym->ts.type == BT_CLASS
7540 && !CLASS_DATA (expr->symtree->n.sym)->attr.class_pointer)
7541 && !expr->symtree->n.sym->attr.allocatable
7542 && !expr->symtree->n.sym->attr.pointer
7543 && !expr->symtree->n.sym->attr.host_assoc
7544 && !expr->symtree->n.sym->attr.use_assoc)
7546 /* Set the offset to -1. */
7547 mpz_t minus_one;
7548 mpz_init_set_si (minus_one, -1);
7549 tmp = gfc_conv_mpz_to_tree (minus_one, gfc_index_integer_kind);
7550 gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
7552 else
7554 /* Only the callee knows what the correct offset it, so just set
7555 it to zero here. */
7556 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
7558 desc = parm;
7561 /* For class arrays add the class tree into the saved descriptor to
7562 enable getting of _vptr and the like. */
7563 if (expr->expr_type == EXPR_VARIABLE && VAR_P (desc)
7564 && IS_CLASS_ARRAY (expr->symtree->n.sym))
7566 gfc_allocate_lang_decl (desc);
7567 GFC_DECL_SAVED_DESCRIPTOR (desc) =
7568 DECL_LANG_SPECIFIC (expr->symtree->n.sym->backend_decl) ?
7569 GFC_DECL_SAVED_DESCRIPTOR (expr->symtree->n.sym->backend_decl)
7570 : expr->symtree->n.sym->backend_decl;
7572 else if (expr->expr_type == EXPR_ARRAY && VAR_P (desc)
7573 && IS_CLASS_ARRAY (expr))
7575 tree vtype;
7576 gfc_allocate_lang_decl (desc);
7577 tmp = gfc_create_var (expr->ts.u.derived->backend_decl, "class");
7578 GFC_DECL_SAVED_DESCRIPTOR (desc) = tmp;
7579 vtype = gfc_class_vptr_get (tmp);
7580 gfc_add_modify (&se->pre, vtype,
7581 gfc_build_addr_expr (TREE_TYPE (vtype),
7582 gfc_find_vtab (&expr->ts)->backend_decl));
7584 if (!se->direct_byref || se->byref_noassign)
7586 /* Get a pointer to the new descriptor. */
7587 if (se->want_pointer)
7588 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7589 else
7590 se->expr = desc;
7593 gfc_add_block_to_block (&se->pre, &loop.pre);
7594 gfc_add_block_to_block (&se->post, &loop.post);
7596 /* Cleanup the scalarizer. */
7597 gfc_cleanup_loop (&loop);
7600 /* Helper function for gfc_conv_array_parameter if array size needs to be
7601 computed. */
7603 static void
7604 array_parameter_size (tree desc, gfc_expr *expr, tree *size)
7606 tree elem;
7607 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7608 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
7609 else if (expr->rank > 1)
7610 *size = build_call_expr_loc (input_location,
7611 gfor_fndecl_size0, 1,
7612 gfc_build_addr_expr (NULL, desc));
7613 else
7615 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
7616 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
7618 *size = fold_build2_loc (input_location, MINUS_EXPR,
7619 gfc_array_index_type, ubound, lbound);
7620 *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7621 *size, gfc_index_one_node);
7622 *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7623 *size, gfc_index_zero_node);
7625 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
7626 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7627 *size, fold_convert (gfc_array_index_type, elem));
7630 /* Convert an array for passing as an actual parameter. */
7631 /* TODO: Optimize passing g77 arrays. */
7633 void
7634 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
7635 const gfc_symbol *fsym, const char *proc_name,
7636 tree *size)
7638 tree ptr;
7639 tree desc;
7640 tree tmp = NULL_TREE;
7641 tree stmt;
7642 tree parent = DECL_CONTEXT (current_function_decl);
7643 bool full_array_var;
7644 bool this_array_result;
7645 bool contiguous;
7646 bool no_pack;
7647 bool array_constructor;
7648 bool good_allocatable;
7649 bool ultimate_ptr_comp;
7650 bool ultimate_alloc_comp;
7651 gfc_symbol *sym;
7652 stmtblock_t block;
7653 gfc_ref *ref;
7655 ultimate_ptr_comp = false;
7656 ultimate_alloc_comp = false;
7658 for (ref = expr->ref; ref; ref = ref->next)
7660 if (ref->next == NULL)
7661 break;
7663 if (ref->type == REF_COMPONENT)
7665 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
7666 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
7670 full_array_var = false;
7671 contiguous = false;
7673 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
7674 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
7676 sym = full_array_var ? expr->symtree->n.sym : NULL;
7678 /* The symbol should have an array specification. */
7679 gcc_assert (!sym || sym->as || ref->u.ar.as);
7681 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
7683 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
7684 expr->ts.u.cl->backend_decl = tmp;
7685 se->string_length = tmp;
7688 /* Is this the result of the enclosing procedure? */
7689 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
7690 if (this_array_result
7691 && (sym->backend_decl != current_function_decl)
7692 && (sym->backend_decl != parent))
7693 this_array_result = false;
7695 /* Passing address of the array if it is not pointer or assumed-shape. */
7696 if (full_array_var && g77 && !this_array_result
7697 && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
7699 tmp = gfc_get_symbol_decl (sym);
7701 if (sym->ts.type == BT_CHARACTER)
7702 se->string_length = sym->ts.u.cl->backend_decl;
7704 if (!sym->attr.pointer
7705 && sym->as
7706 && sym->as->type != AS_ASSUMED_SHAPE
7707 && sym->as->type != AS_DEFERRED
7708 && sym->as->type != AS_ASSUMED_RANK
7709 && !sym->attr.allocatable)
7711 /* Some variables are declared directly, others are declared as
7712 pointers and allocated on the heap. */
7713 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
7714 se->expr = tmp;
7715 else
7716 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
7717 if (size)
7718 array_parameter_size (tmp, expr, size);
7719 return;
7722 if (sym->attr.allocatable)
7724 if (sym->attr.dummy || sym->attr.result)
7726 gfc_conv_expr_descriptor (se, expr);
7727 tmp = se->expr;
7729 if (size)
7730 array_parameter_size (tmp, expr, size);
7731 se->expr = gfc_conv_array_data (tmp);
7732 return;
7736 /* A convenient reduction in scope. */
7737 contiguous = g77 && !this_array_result && contiguous;
7739 /* There is no need to pack and unpack the array, if it is contiguous
7740 and not a deferred- or assumed-shape array, or if it is simply
7741 contiguous. */
7742 no_pack = ((sym && sym->as
7743 && !sym->attr.pointer
7744 && sym->as->type != AS_DEFERRED
7745 && sym->as->type != AS_ASSUMED_RANK
7746 && sym->as->type != AS_ASSUMED_SHAPE)
7748 (ref && ref->u.ar.as
7749 && ref->u.ar.as->type != AS_DEFERRED
7750 && ref->u.ar.as->type != AS_ASSUMED_RANK
7751 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
7753 gfc_is_simply_contiguous (expr, false, true));
7755 no_pack = contiguous && no_pack;
7757 /* Array constructors are always contiguous and do not need packing. */
7758 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
7760 /* Same is true of contiguous sections from allocatable variables. */
7761 good_allocatable = contiguous
7762 && expr->symtree
7763 && expr->symtree->n.sym->attr.allocatable;
7765 /* Or ultimate allocatable components. */
7766 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
7768 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
7770 gfc_conv_expr_descriptor (se, expr);
7771 /* Deallocate the allocatable components of structures that are
7772 not variable. */
7773 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
7774 && expr->ts.u.derived->attr.alloc_comp
7775 && expr->expr_type != EXPR_VARIABLE)
7777 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se->expr, expr->rank);
7779 /* The components shall be deallocated before their containing entity. */
7780 gfc_prepend_expr_to_block (&se->post, tmp);
7782 if (expr->ts.type == BT_CHARACTER)
7783 se->string_length = expr->ts.u.cl->backend_decl;
7784 if (size)
7785 array_parameter_size (se->expr, expr, size);
7786 se->expr = gfc_conv_array_data (se->expr);
7787 return;
7790 if (this_array_result)
7792 /* Result of the enclosing function. */
7793 gfc_conv_expr_descriptor (se, expr);
7794 if (size)
7795 array_parameter_size (se->expr, expr, size);
7796 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7798 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
7799 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
7800 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
7801 se->expr));
7803 return;
7805 else
7807 /* Every other type of array. */
7808 se->want_pointer = 1;
7809 gfc_conv_expr_descriptor (se, expr);
7811 if (size)
7812 array_parameter_size (build_fold_indirect_ref_loc (input_location,
7813 se->expr),
7814 expr, size);
7817 /* Deallocate the allocatable components of structures that are
7818 not variable, for descriptorless arguments.
7819 Arguments with a descriptor are handled in gfc_conv_procedure_call. */
7820 if (g77 && (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
7821 && expr->ts.u.derived->attr.alloc_comp
7822 && expr->expr_type != EXPR_VARIABLE)
7824 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
7825 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
7827 /* The components shall be deallocated before their containing entity. */
7828 gfc_prepend_expr_to_block (&se->post, tmp);
7831 if (g77 || (fsym && fsym->attr.contiguous
7832 && !gfc_is_simply_contiguous (expr, false, true)))
7834 tree origptr = NULL_TREE;
7836 desc = se->expr;
7838 /* For contiguous arrays, save the original value of the descriptor. */
7839 if (!g77)
7841 origptr = gfc_create_var (pvoid_type_node, "origptr");
7842 tmp = build_fold_indirect_ref_loc (input_location, desc);
7843 tmp = gfc_conv_array_data (tmp);
7844 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7845 TREE_TYPE (origptr), origptr,
7846 fold_convert (TREE_TYPE (origptr), tmp));
7847 gfc_add_expr_to_block (&se->pre, tmp);
7850 /* Repack the array. */
7851 if (warn_array_temporaries)
7853 if (fsym)
7854 gfc_warning (OPT_Warray_temporaries,
7855 "Creating array temporary at %L for argument %qs",
7856 &expr->where, fsym->name);
7857 else
7858 gfc_warning (OPT_Warray_temporaries,
7859 "Creating array temporary at %L", &expr->where);
7862 ptr = build_call_expr_loc (input_location,
7863 gfor_fndecl_in_pack, 1, desc);
7865 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7867 tmp = gfc_conv_expr_present (sym);
7868 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
7869 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
7870 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
7873 ptr = gfc_evaluate_now (ptr, &se->pre);
7875 /* Use the packed data for the actual argument, except for contiguous arrays,
7876 where the descriptor's data component is set. */
7877 if (g77)
7878 se->expr = ptr;
7879 else
7881 tmp = build_fold_indirect_ref_loc (input_location, desc);
7883 gfc_ss * ss = gfc_walk_expr (expr);
7884 if (!transposed_dims (ss))
7885 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
7886 else
7888 tree old_field, new_field;
7890 /* The original descriptor has transposed dims so we can't reuse
7891 it directly; we have to create a new one. */
7892 tree old_desc = tmp;
7893 tree new_desc = gfc_create_var (TREE_TYPE (old_desc), "arg_desc");
7895 old_field = gfc_conv_descriptor_dtype (old_desc);
7896 new_field = gfc_conv_descriptor_dtype (new_desc);
7897 gfc_add_modify (&se->pre, new_field, old_field);
7899 old_field = gfc_conv_descriptor_offset (old_desc);
7900 new_field = gfc_conv_descriptor_offset (new_desc);
7901 gfc_add_modify (&se->pre, new_field, old_field);
7903 for (int i = 0; i < expr->rank; i++)
7905 old_field = gfc_conv_descriptor_dimension (old_desc,
7906 gfc_rank_cst[get_array_ref_dim_for_loop_dim (ss, i)]);
7907 new_field = gfc_conv_descriptor_dimension (new_desc,
7908 gfc_rank_cst[i]);
7909 gfc_add_modify (&se->pre, new_field, old_field);
7912 if (flag_coarray == GFC_FCOARRAY_LIB
7913 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (old_desc))
7914 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (old_desc))
7915 == GFC_ARRAY_ALLOCATABLE)
7917 old_field = gfc_conv_descriptor_token (old_desc);
7918 new_field = gfc_conv_descriptor_token (new_desc);
7919 gfc_add_modify (&se->pre, new_field, old_field);
7922 gfc_conv_descriptor_data_set (&se->pre, new_desc, ptr);
7923 se->expr = gfc_build_addr_expr (NULL_TREE, new_desc);
7925 gfc_free_ss (ss);
7928 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
7930 char * msg;
7932 if (fsym && proc_name)
7933 msg = xasprintf ("An array temporary was created for argument "
7934 "'%s' of procedure '%s'", fsym->name, proc_name);
7935 else
7936 msg = xasprintf ("An array temporary was created");
7938 tmp = build_fold_indirect_ref_loc (input_location,
7939 desc);
7940 tmp = gfc_conv_array_data (tmp);
7941 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7942 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7944 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7945 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7946 logical_type_node,
7947 gfc_conv_expr_present (sym), tmp);
7949 gfc_trans_runtime_check (false, true, tmp, &se->pre,
7950 &expr->where, msg);
7951 free (msg);
7954 gfc_start_block (&block);
7956 /* Copy the data back. */
7957 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
7959 tmp = build_call_expr_loc (input_location,
7960 gfor_fndecl_in_unpack, 2, desc, ptr);
7961 gfc_add_expr_to_block (&block, tmp);
7964 /* Free the temporary. */
7965 tmp = gfc_call_free (ptr);
7966 gfc_add_expr_to_block (&block, tmp);
7968 stmt = gfc_finish_block (&block);
7970 gfc_init_block (&block);
7971 /* Only if it was repacked. This code needs to be executed before the
7972 loop cleanup code. */
7973 tmp = build_fold_indirect_ref_loc (input_location,
7974 desc);
7975 tmp = gfc_conv_array_data (tmp);
7976 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7977 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7979 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7980 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7981 logical_type_node,
7982 gfc_conv_expr_present (sym), tmp);
7984 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
7986 gfc_add_expr_to_block (&block, tmp);
7987 gfc_add_block_to_block (&block, &se->post);
7989 gfc_init_block (&se->post);
7991 /* Reset the descriptor pointer. */
7992 if (!g77)
7994 tmp = build_fold_indirect_ref_loc (input_location, desc);
7995 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
7998 gfc_add_block_to_block (&se->post, &block);
8003 /* This helper function calculates the size in words of a full array. */
8005 tree
8006 gfc_full_array_size (stmtblock_t *block, tree decl, int rank)
8008 tree idx;
8009 tree nelems;
8010 tree tmp;
8011 idx = gfc_rank_cst[rank - 1];
8012 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
8013 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
8014 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8015 nelems, tmp);
8016 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8017 tmp, gfc_index_one_node);
8018 tmp = gfc_evaluate_now (tmp, block);
8020 nelems = gfc_conv_descriptor_stride_get (decl, idx);
8021 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8022 nelems, tmp);
8023 return gfc_evaluate_now (tmp, block);
8027 /* Allocate dest to the same size as src, and copy src -> dest.
8028 If no_malloc is set, only the copy is done. */
8030 static tree
8031 duplicate_allocatable (tree dest, tree src, tree type, int rank,
8032 bool no_malloc, bool no_memcpy, tree str_sz,
8033 tree add_when_allocated)
8035 tree tmp;
8036 tree size;
8037 tree nelems;
8038 tree null_cond;
8039 tree null_data;
8040 stmtblock_t block;
8042 /* If the source is null, set the destination to null. Then,
8043 allocate memory to the destination. */
8044 gfc_init_block (&block);
8046 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8048 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
8049 null_data = gfc_finish_block (&block);
8051 gfc_init_block (&block);
8052 if (str_sz != NULL_TREE)
8053 size = str_sz;
8054 else
8055 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8057 if (!no_malloc)
8059 tmp = gfc_call_malloc (&block, type, size);
8060 gfc_add_modify (&block, dest, fold_convert (type, tmp));
8063 if (!no_memcpy)
8065 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8066 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8067 fold_convert (size_type_node, size));
8068 gfc_add_expr_to_block (&block, tmp);
8071 else
8073 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8074 null_data = gfc_finish_block (&block);
8076 gfc_init_block (&block);
8077 if (rank)
8078 nelems = gfc_full_array_size (&block, src, rank);
8079 else
8080 nelems = gfc_index_one_node;
8082 if (str_sz != NULL_TREE)
8083 tmp = fold_convert (gfc_array_index_type, str_sz);
8084 else
8085 tmp = fold_convert (gfc_array_index_type,
8086 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
8087 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8088 nelems, tmp);
8089 if (!no_malloc)
8091 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
8092 tmp = gfc_call_malloc (&block, tmp, size);
8093 gfc_conv_descriptor_data_set (&block, dest, tmp);
8096 /* We know the temporary and the value will be the same length,
8097 so can use memcpy. */
8098 if (!no_memcpy)
8100 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8101 tmp = build_call_expr_loc (input_location, tmp, 3,
8102 gfc_conv_descriptor_data_get (dest),
8103 gfc_conv_descriptor_data_get (src),
8104 fold_convert (size_type_node, size));
8105 gfc_add_expr_to_block (&block, tmp);
8109 gfc_add_expr_to_block (&block, add_when_allocated);
8110 tmp = gfc_finish_block (&block);
8112 /* Null the destination if the source is null; otherwise do
8113 the allocate and copy. */
8114 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
8115 null_cond = src;
8116 else
8117 null_cond = gfc_conv_descriptor_data_get (src);
8119 null_cond = convert (pvoid_type_node, null_cond);
8120 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8121 null_cond, null_pointer_node);
8122 return build3_v (COND_EXPR, null_cond, tmp, null_data);
8126 /* Allocate dest to the same size as src, and copy data src -> dest. */
8128 tree
8129 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank,
8130 tree add_when_allocated)
8132 return duplicate_allocatable (dest, src, type, rank, false, false,
8133 NULL_TREE, add_when_allocated);
8137 /* Copy data src -> dest. */
8139 tree
8140 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
8142 return duplicate_allocatable (dest, src, type, rank, true, false,
8143 NULL_TREE, NULL_TREE);
8146 /* Allocate dest to the same size as src, but don't copy anything. */
8148 tree
8149 gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
8151 return duplicate_allocatable (dest, src, type, rank, false, true,
8152 NULL_TREE, NULL_TREE);
8156 static tree
8157 duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
8158 tree type, int rank)
8160 tree tmp;
8161 tree size;
8162 tree nelems;
8163 tree null_cond;
8164 tree null_data;
8165 stmtblock_t block, globalblock;
8167 /* If the source is null, set the destination to null. Then,
8168 allocate memory to the destination. */
8169 gfc_init_block (&block);
8170 gfc_init_block (&globalblock);
8172 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8174 gfc_se se;
8175 symbol_attribute attr;
8176 tree dummy_desc;
8178 gfc_init_se (&se, NULL);
8179 gfc_clear_attr (&attr);
8180 attr.allocatable = 1;
8181 dummy_desc = gfc_conv_scalar_to_descriptor (&se, dest, attr);
8182 gfc_add_block_to_block (&globalblock, &se.pre);
8183 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8185 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
8186 gfc_allocate_using_caf_lib (&block, dummy_desc, size,
8187 gfc_build_addr_expr (NULL_TREE, dest_tok),
8188 NULL_TREE, NULL_TREE, NULL_TREE,
8189 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8190 null_data = gfc_finish_block (&block);
8192 gfc_init_block (&block);
8194 gfc_allocate_using_caf_lib (&block, dummy_desc,
8195 fold_convert (size_type_node, size),
8196 gfc_build_addr_expr (NULL_TREE, dest_tok),
8197 NULL_TREE, NULL_TREE, NULL_TREE,
8198 GFC_CAF_COARRAY_ALLOC);
8200 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8201 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8202 fold_convert (size_type_node, size));
8203 gfc_add_expr_to_block (&block, tmp);
8205 else
8207 /* Set the rank or unitialized memory access may be reported. */
8208 tmp = gfc_conv_descriptor_dtype (dest);
8209 gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank));
8211 if (rank)
8212 nelems = gfc_full_array_size (&block, src, rank);
8213 else
8214 nelems = integer_one_node;
8216 tmp = fold_convert (size_type_node,
8217 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
8218 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
8219 fold_convert (size_type_node, nelems), tmp);
8221 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8222 gfc_allocate_using_caf_lib (&block, dest, fold_convert (size_type_node,
8223 size),
8224 gfc_build_addr_expr (NULL_TREE, dest_tok),
8225 NULL_TREE, NULL_TREE, NULL_TREE,
8226 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8227 null_data = gfc_finish_block (&block);
8229 gfc_init_block (&block);
8230 gfc_allocate_using_caf_lib (&block, dest,
8231 fold_convert (size_type_node, size),
8232 gfc_build_addr_expr (NULL_TREE, dest_tok),
8233 NULL_TREE, NULL_TREE, NULL_TREE,
8234 GFC_CAF_COARRAY_ALLOC);
8236 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8237 tmp = build_call_expr_loc (input_location, tmp, 3,
8238 gfc_conv_descriptor_data_get (dest),
8239 gfc_conv_descriptor_data_get (src),
8240 fold_convert (size_type_node, size));
8241 gfc_add_expr_to_block (&block, tmp);
8244 tmp = gfc_finish_block (&block);
8246 /* Null the destination if the source is null; otherwise do
8247 the register and copy. */
8248 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
8249 null_cond = src;
8250 else
8251 null_cond = gfc_conv_descriptor_data_get (src);
8253 null_cond = convert (pvoid_type_node, null_cond);
8254 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8255 null_cond, null_pointer_node);
8256 gfc_add_expr_to_block (&globalblock, build3_v (COND_EXPR, null_cond, tmp,
8257 null_data));
8258 return gfc_finish_block (&globalblock);
8262 /* Helper function to abstract whether coarray processing is enabled. */
8264 static bool
8265 caf_enabled (int caf_mode)
8267 return (caf_mode & GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY)
8268 == GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY;
8272 /* Helper function to abstract whether coarray processing is enabled
8273 and we are in a derived type coarray. */
8275 static bool
8276 caf_in_coarray (int caf_mode)
8278 static const int pat = GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
8279 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY;
8280 return (caf_mode & pat) == pat;
8284 /* Helper function to abstract whether coarray is to deallocate only. */
8286 bool
8287 gfc_caf_is_dealloc_only (int caf_mode)
8289 return (caf_mode & GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY)
8290 == GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY;
8294 /* Recursively traverse an object of derived type, generating code to
8295 deallocate, nullify or copy allocatable components. This is the work horse
8296 function for the functions named in this enum. */
8298 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP,
8299 COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP, REASSIGN_CAF_COMP,
8300 ALLOCATE_PDT_COMP, DEALLOCATE_PDT_COMP, CHECK_PDT_DUMMY};
8302 static gfc_actual_arglist *pdt_param_list;
8304 static tree
8305 structure_alloc_comps (gfc_symbol * der_type, tree decl,
8306 tree dest, int rank, int purpose, int caf_mode)
8308 gfc_component *c;
8309 gfc_loopinfo loop;
8310 stmtblock_t fnblock;
8311 stmtblock_t loopbody;
8312 stmtblock_t tmpblock;
8313 tree decl_type;
8314 tree tmp;
8315 tree comp;
8316 tree dcmp;
8317 tree nelems;
8318 tree index;
8319 tree var;
8320 tree cdecl;
8321 tree ctype;
8322 tree vref, dref;
8323 tree null_cond = NULL_TREE;
8324 tree add_when_allocated;
8325 tree dealloc_fndecl;
8326 tree caf_token;
8327 gfc_symbol *vtab;
8328 int caf_dereg_mode;
8329 symbol_attribute *attr;
8330 bool deallocate_called;
8332 gfc_init_block (&fnblock);
8334 decl_type = TREE_TYPE (decl);
8336 if ((POINTER_TYPE_P (decl_type))
8337 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
8339 decl = build_fold_indirect_ref_loc (input_location, decl);
8340 /* Deref dest in sync with decl, but only when it is not NULL. */
8341 if (dest)
8342 dest = build_fold_indirect_ref_loc (input_location, dest);
8344 /* Update the decl_type because it got dereferenced. */
8345 decl_type = TREE_TYPE (decl);
8348 /* If this is an array of derived types with allocatable components
8349 build a loop and recursively call this function. */
8350 if (TREE_CODE (decl_type) == ARRAY_TYPE
8351 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
8353 tmp = gfc_conv_array_data (decl);
8354 var = build_fold_indirect_ref_loc (input_location, tmp);
8356 /* Get the number of elements - 1 and set the counter. */
8357 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
8359 /* Use the descriptor for an allocatable array. Since this
8360 is a full array reference, we only need the descriptor
8361 information from dimension = rank. */
8362 tmp = gfc_full_array_size (&fnblock, decl, rank);
8363 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8364 gfc_array_index_type, tmp,
8365 gfc_index_one_node);
8367 null_cond = gfc_conv_descriptor_data_get (decl);
8368 null_cond = fold_build2_loc (input_location, NE_EXPR,
8369 logical_type_node, null_cond,
8370 build_int_cst (TREE_TYPE (null_cond), 0));
8372 else
8374 /* Otherwise use the TYPE_DOMAIN information. */
8375 tmp = array_type_nelts (decl_type);
8376 tmp = fold_convert (gfc_array_index_type, tmp);
8379 /* Remember that this is, in fact, the no. of elements - 1. */
8380 nelems = gfc_evaluate_now (tmp, &fnblock);
8381 index = gfc_create_var (gfc_array_index_type, "S");
8383 /* Build the body of the loop. */
8384 gfc_init_block (&loopbody);
8386 vref = gfc_build_array_ref (var, index, NULL);
8388 if ((purpose == COPY_ALLOC_COMP || purpose == COPY_ONLY_ALLOC_COMP)
8389 && !caf_enabled (caf_mode))
8391 tmp = build_fold_indirect_ref_loc (input_location,
8392 gfc_conv_array_data (dest));
8393 dref = gfc_build_array_ref (tmp, index, NULL);
8394 tmp = structure_alloc_comps (der_type, vref, dref, rank,
8395 COPY_ALLOC_COMP, 0);
8397 else
8398 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose,
8399 caf_mode);
8401 gfc_add_expr_to_block (&loopbody, tmp);
8403 /* Build the loop and return. */
8404 gfc_init_loopinfo (&loop);
8405 loop.dimen = 1;
8406 loop.from[0] = gfc_index_zero_node;
8407 loop.loopvar[0] = index;
8408 loop.to[0] = nelems;
8409 gfc_trans_scalarizing_loops (&loop, &loopbody);
8410 gfc_add_block_to_block (&fnblock, &loop.pre);
8412 tmp = gfc_finish_block (&fnblock);
8413 /* When copying allocateable components, the above implements the
8414 deep copy. Nevertheless is a deep copy only allowed, when the current
8415 component is allocated, for which code will be generated in
8416 gfc_duplicate_allocatable (), where the deep copy code is just added
8417 into the if's body, by adding tmp (the deep copy code) as last
8418 argument to gfc_duplicate_allocatable (). */
8419 if (purpose == COPY_ALLOC_COMP
8420 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8421 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank,
8422 tmp);
8423 else if (null_cond != NULL_TREE)
8424 tmp = build3_v (COND_EXPR, null_cond, tmp,
8425 build_empty_stmt (input_location));
8427 return tmp;
8430 if (purpose == DEALLOCATE_ALLOC_COMP && der_type->attr.pdt_type)
8432 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
8433 DEALLOCATE_PDT_COMP, 0);
8434 gfc_add_expr_to_block (&fnblock, tmp);
8436 else if (purpose == ALLOCATE_PDT_COMP && der_type->attr.alloc_comp)
8438 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
8439 NULLIFY_ALLOC_COMP, 0);
8440 gfc_add_expr_to_block (&fnblock, tmp);
8443 /* Otherwise, act on the components or recursively call self to
8444 act on a chain of components. */
8445 for (c = der_type->components; c; c = c->next)
8447 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
8448 || c->ts.type == BT_CLASS)
8449 && c->ts.u.derived->attr.alloc_comp;
8450 bool same_type = (c->ts.type == BT_DERIVED && der_type == c->ts.u.derived)
8451 || (c->ts.type == BT_CLASS && der_type == CLASS_DATA (c)->ts.u.derived);
8453 bool is_pdt_type = c->ts.type == BT_DERIVED
8454 && c->ts.u.derived->attr.pdt_type;
8456 cdecl = c->backend_decl;
8457 ctype = TREE_TYPE (cdecl);
8459 switch (purpose)
8461 case DEALLOCATE_ALLOC_COMP:
8463 gfc_init_block (&tmpblock);
8465 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8466 decl, cdecl, NULL_TREE);
8468 /* Shortcut to get the attributes of the component. */
8469 if (c->ts.type == BT_CLASS)
8471 attr = &CLASS_DATA (c)->attr;
8472 if (attr->class_pointer)
8473 continue;
8475 else
8477 attr = &c->attr;
8478 if (attr->pointer)
8479 continue;
8482 if ((c->ts.type == BT_DERIVED && !c->attr.pointer)
8483 || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer))
8484 /* Call the finalizer, which will free the memory and nullify the
8485 pointer of an array. */
8486 deallocate_called = gfc_add_comp_finalizer_call (&tmpblock, comp, c,
8487 caf_enabled (caf_mode))
8488 && attr->dimension;
8489 else
8490 deallocate_called = false;
8492 /* Add the _class ref for classes. */
8493 if (c->ts.type == BT_CLASS && attr->allocatable)
8494 comp = gfc_class_data_get (comp);
8496 add_when_allocated = NULL_TREE;
8497 if (cmp_has_alloc_comps
8498 && !c->attr.pointer && !c->attr.proc_pointer
8499 && !same_type
8500 && !deallocate_called)
8502 /* Add checked deallocation of the components. This code is
8503 obviously added because the finalizer is not trusted to free
8504 all memory. */
8505 if (c->ts.type == BT_CLASS)
8507 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
8508 add_when_allocated
8509 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
8510 comp, NULL_TREE, rank, purpose,
8511 caf_mode);
8513 else
8515 rank = c->as ? c->as->rank : 0;
8516 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
8517 comp, NULL_TREE,
8518 rank, purpose,
8519 caf_mode);
8523 if (attr->allocatable && !same_type
8524 && (!attr->codimension || caf_enabled (caf_mode)))
8526 /* Handle all types of components besides components of the
8527 same_type as the current one, because those would create an
8528 endless loop. */
8529 caf_dereg_mode
8530 = (caf_in_coarray (caf_mode) || attr->codimension)
8531 ? (gfc_caf_is_dealloc_only (caf_mode)
8532 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
8533 : GFC_CAF_COARRAY_DEREGISTER)
8534 : GFC_CAF_COARRAY_NOCOARRAY;
8536 caf_token = NULL_TREE;
8537 /* Coarray components are handled directly by
8538 deallocate_with_status. */
8539 if (!attr->codimension
8540 && caf_dereg_mode != GFC_CAF_COARRAY_NOCOARRAY)
8542 if (c->caf_token)
8543 caf_token = fold_build3_loc (input_location, COMPONENT_REF,
8544 TREE_TYPE (c->caf_token),
8545 decl, c->caf_token, NULL_TREE);
8546 else if (attr->dimension && !attr->proc_pointer)
8547 caf_token = gfc_conv_descriptor_token (comp);
8549 if (attr->dimension && !attr->codimension && !attr->proc_pointer)
8550 /* When this is an array but not in conjunction with a coarray
8551 then add the data-ref. For coarray'ed arrays the data-ref
8552 is added by deallocate_with_status. */
8553 comp = gfc_conv_descriptor_data_get (comp);
8555 tmp = gfc_deallocate_with_status (comp, NULL_TREE, NULL_TREE,
8556 NULL_TREE, NULL_TREE, true,
8557 NULL, caf_dereg_mode,
8558 add_when_allocated, caf_token);
8560 gfc_add_expr_to_block (&tmpblock, tmp);
8562 else if (attr->allocatable && !attr->codimension
8563 && !deallocate_called)
8565 /* Case of recursive allocatable derived types. */
8566 tree is_allocated;
8567 tree ubound;
8568 tree cdesc;
8569 stmtblock_t dealloc_block;
8571 gfc_init_block (&dealloc_block);
8572 if (add_when_allocated)
8573 gfc_add_expr_to_block (&dealloc_block, add_when_allocated);
8575 /* Convert the component into a rank 1 descriptor type. */
8576 if (attr->dimension)
8578 tmp = gfc_get_element_type (TREE_TYPE (comp));
8579 ubound = gfc_full_array_size (&dealloc_block, comp,
8580 c->ts.type == BT_CLASS
8581 ? CLASS_DATA (c)->as->rank
8582 : c->as->rank);
8584 else
8586 tmp = TREE_TYPE (comp);
8587 ubound = build_int_cst (gfc_array_index_type, 1);
8590 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
8591 &ubound, 1,
8592 GFC_ARRAY_ALLOCATABLE, false);
8594 cdesc = gfc_create_var (cdesc, "cdesc");
8595 DECL_ARTIFICIAL (cdesc) = 1;
8597 gfc_add_modify (&dealloc_block, gfc_conv_descriptor_dtype (cdesc),
8598 gfc_get_dtype_rank_type (1, tmp));
8599 gfc_conv_descriptor_lbound_set (&dealloc_block, cdesc,
8600 gfc_index_zero_node,
8601 gfc_index_one_node);
8602 gfc_conv_descriptor_stride_set (&dealloc_block, cdesc,
8603 gfc_index_zero_node,
8604 gfc_index_one_node);
8605 gfc_conv_descriptor_ubound_set (&dealloc_block, cdesc,
8606 gfc_index_zero_node, ubound);
8608 if (attr->dimension)
8609 comp = gfc_conv_descriptor_data_get (comp);
8611 gfc_conv_descriptor_data_set (&dealloc_block, cdesc, comp);
8613 /* Now call the deallocator. */
8614 vtab = gfc_find_vtab (&c->ts);
8615 if (vtab->backend_decl == NULL)
8616 gfc_get_symbol_decl (vtab);
8617 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
8618 dealloc_fndecl = gfc_vptr_deallocate_get (tmp);
8619 dealloc_fndecl = build_fold_indirect_ref_loc (input_location,
8620 dealloc_fndecl);
8621 tmp = build_int_cst (TREE_TYPE (comp), 0);
8622 is_allocated = fold_build2_loc (input_location, NE_EXPR,
8623 logical_type_node, tmp,
8624 comp);
8625 cdesc = gfc_build_addr_expr (NULL_TREE, cdesc);
8627 tmp = build_call_expr_loc (input_location,
8628 dealloc_fndecl, 1,
8629 cdesc);
8630 gfc_add_expr_to_block (&dealloc_block, tmp);
8632 tmp = gfc_finish_block (&dealloc_block);
8634 tmp = fold_build3_loc (input_location, COND_EXPR,
8635 void_type_node, is_allocated, tmp,
8636 build_empty_stmt (input_location));
8638 gfc_add_expr_to_block (&tmpblock, tmp);
8640 else if (add_when_allocated)
8641 gfc_add_expr_to_block (&tmpblock, add_when_allocated);
8643 if (c->ts.type == BT_CLASS && attr->allocatable
8644 && (!attr->codimension || !caf_enabled (caf_mode)))
8646 /* Finally, reset the vptr to the declared type vtable and, if
8647 necessary reset the _len field.
8649 First recover the reference to the component and obtain
8650 the vptr. */
8651 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8652 decl, cdecl, NULL_TREE);
8653 tmp = gfc_class_vptr_get (comp);
8655 if (UNLIMITED_POLY (c))
8657 /* Both vptr and _len field should be nulled. */
8658 gfc_add_modify (&tmpblock, tmp,
8659 build_int_cst (TREE_TYPE (tmp), 0));
8660 tmp = gfc_class_len_get (comp);
8661 gfc_add_modify (&tmpblock, tmp,
8662 build_int_cst (TREE_TYPE (tmp), 0));
8664 else
8666 /* Build the vtable address and set the vptr with it. */
8667 tree vtab;
8668 gfc_symbol *vtable;
8669 vtable = gfc_find_derived_vtab (c->ts.u.derived);
8670 vtab = vtable->backend_decl;
8671 if (vtab == NULL_TREE)
8672 vtab = gfc_get_symbol_decl (vtable);
8673 vtab = gfc_build_addr_expr (NULL, vtab);
8674 vtab = fold_convert (TREE_TYPE (tmp), vtab);
8675 gfc_add_modify (&tmpblock, tmp, vtab);
8679 /* Now add the deallocation of this component. */
8680 gfc_add_block_to_block (&fnblock, &tmpblock);
8681 break;
8683 case NULLIFY_ALLOC_COMP:
8684 /* Nullify
8685 - allocatable components (regular or in class)
8686 - components that have allocatable components
8687 - pointer components when in a coarray.
8688 Skip everything else especially proc_pointers, which may come
8689 coupled with the regular pointer attribute. */
8690 if (c->attr.proc_pointer
8691 || !(c->attr.allocatable || (c->ts.type == BT_CLASS
8692 && CLASS_DATA (c)->attr.allocatable)
8693 || (cmp_has_alloc_comps
8694 && ((c->ts.type == BT_DERIVED && !c->attr.pointer)
8695 || (c->ts.type == BT_CLASS
8696 && !CLASS_DATA (c)->attr.class_pointer)))
8697 || (caf_in_coarray (caf_mode) && c->attr.pointer)))
8698 continue;
8700 /* Process class components first, because they always have the
8701 pointer-attribute set which would be caught wrong else. */
8702 if (c->ts.type == BT_CLASS
8703 && (CLASS_DATA (c)->attr.allocatable
8704 || CLASS_DATA (c)->attr.class_pointer))
8706 /* Allocatable CLASS components. */
8707 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8708 decl, cdecl, NULL_TREE);
8710 comp = gfc_class_data_get (comp);
8711 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
8712 gfc_conv_descriptor_data_set (&fnblock, comp,
8713 null_pointer_node);
8714 else
8716 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8717 void_type_node, comp,
8718 build_int_cst (TREE_TYPE (comp), 0));
8719 gfc_add_expr_to_block (&fnblock, tmp);
8721 cmp_has_alloc_comps = false;
8723 /* Coarrays need the component to be nulled before the api-call
8724 is made. */
8725 else if (c->attr.pointer || c->attr.allocatable)
8727 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8728 decl, cdecl, NULL_TREE);
8729 if (c->attr.dimension || c->attr.codimension)
8730 gfc_conv_descriptor_data_set (&fnblock, comp,
8731 null_pointer_node);
8732 else
8733 gfc_add_modify (&fnblock, comp,
8734 build_int_cst (TREE_TYPE (comp), 0));
8735 if (gfc_deferred_strlen (c, &comp))
8737 comp = fold_build3_loc (input_location, COMPONENT_REF,
8738 TREE_TYPE (comp),
8739 decl, comp, NULL_TREE);
8740 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8741 TREE_TYPE (comp), comp,
8742 build_int_cst (TREE_TYPE (comp), 0));
8743 gfc_add_expr_to_block (&fnblock, tmp);
8745 cmp_has_alloc_comps = false;
8748 if (flag_coarray == GFC_FCOARRAY_LIB
8749 && (caf_in_coarray (caf_mode) || c->attr.codimension))
8751 /* Register the component with the coarray library. */
8752 tree token;
8754 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8755 decl, cdecl, NULL_TREE);
8756 if (c->attr.dimension || c->attr.codimension)
8758 /* Set the dtype, because caf_register needs it. */
8759 gfc_add_modify (&fnblock, gfc_conv_descriptor_dtype (comp),
8760 gfc_get_dtype (TREE_TYPE (comp)));
8761 tmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8762 decl, cdecl, NULL_TREE);
8763 token = gfc_conv_descriptor_token (tmp);
8765 else
8767 gfc_se se;
8769 gfc_init_se (&se, NULL);
8770 token = fold_build3_loc (input_location, COMPONENT_REF,
8771 pvoid_type_node, decl, c->caf_token,
8772 NULL_TREE);
8773 comp = gfc_conv_scalar_to_descriptor (&se, comp,
8774 c->ts.type == BT_CLASS
8775 ? CLASS_DATA (c)->attr
8776 : c->attr);
8777 gfc_add_block_to_block (&fnblock, &se.pre);
8780 gfc_allocate_using_caf_lib (&fnblock, comp, size_zero_node,
8781 gfc_build_addr_expr (NULL_TREE,
8782 token),
8783 NULL_TREE, NULL_TREE, NULL_TREE,
8784 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8787 if (cmp_has_alloc_comps)
8789 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8790 decl, cdecl, NULL_TREE);
8791 rank = c->as ? c->as->rank : 0;
8792 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
8793 rank, purpose, caf_mode);
8794 gfc_add_expr_to_block (&fnblock, tmp);
8796 break;
8798 case REASSIGN_CAF_COMP:
8799 if (caf_enabled (caf_mode)
8800 && (c->attr.codimension
8801 || (c->ts.type == BT_CLASS
8802 && (CLASS_DATA (c)->attr.coarray_comp
8803 || caf_in_coarray (caf_mode)))
8804 || (c->ts.type == BT_DERIVED
8805 && (c->ts.u.derived->attr.coarray_comp
8806 || caf_in_coarray (caf_mode))))
8807 && !same_type)
8809 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8810 decl, cdecl, NULL_TREE);
8811 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8812 dest, cdecl, NULL_TREE);
8814 if (c->attr.codimension)
8816 if (c->ts.type == BT_CLASS)
8818 comp = gfc_class_data_get (comp);
8819 dcmp = gfc_class_data_get (dcmp);
8821 gfc_conv_descriptor_data_set (&fnblock, dcmp,
8822 gfc_conv_descriptor_data_get (comp));
8824 else
8826 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
8827 rank, purpose, caf_mode
8828 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY);
8829 gfc_add_expr_to_block (&fnblock, tmp);
8832 break;
8834 case COPY_ALLOC_COMP:
8835 if (c->attr.pointer)
8836 continue;
8838 /* We need source and destination components. */
8839 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
8840 cdecl, NULL_TREE);
8841 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
8842 cdecl, NULL_TREE);
8843 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
8845 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
8847 tree ftn_tree;
8848 tree size;
8849 tree dst_data;
8850 tree src_data;
8851 tree null_data;
8853 dst_data = gfc_class_data_get (dcmp);
8854 src_data = gfc_class_data_get (comp);
8855 size = fold_convert (size_type_node,
8856 gfc_class_vtab_size_get (comp));
8858 if (CLASS_DATA (c)->attr.dimension)
8860 nelems = gfc_conv_descriptor_size (src_data,
8861 CLASS_DATA (c)->as->rank);
8862 size = fold_build2_loc (input_location, MULT_EXPR,
8863 size_type_node, size,
8864 fold_convert (size_type_node,
8865 nelems));
8867 else
8868 nelems = build_int_cst (size_type_node, 1);
8870 if (CLASS_DATA (c)->attr.dimension
8871 || CLASS_DATA (c)->attr.codimension)
8873 src_data = gfc_conv_descriptor_data_get (src_data);
8874 dst_data = gfc_conv_descriptor_data_get (dst_data);
8877 gfc_init_block (&tmpblock);
8879 /* Coarray component have to have the same allocation status and
8880 shape/type-parameter/effective-type on the LHS and RHS of an
8881 intrinsic assignment. Hence, we did not deallocated them - and
8882 do not allocate them here. */
8883 if (!CLASS_DATA (c)->attr.codimension)
8885 ftn_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
8886 tmp = build_call_expr_loc (input_location, ftn_tree, 1, size);
8887 gfc_add_modify (&tmpblock, dst_data,
8888 fold_convert (TREE_TYPE (dst_data), tmp));
8891 tmp = gfc_copy_class_to_class (comp, dcmp, nelems,
8892 UNLIMITED_POLY (c));
8893 gfc_add_expr_to_block (&tmpblock, tmp);
8894 tmp = gfc_finish_block (&tmpblock);
8896 gfc_init_block (&tmpblock);
8897 gfc_add_modify (&tmpblock, dst_data,
8898 fold_convert (TREE_TYPE (dst_data),
8899 null_pointer_node));
8900 null_data = gfc_finish_block (&tmpblock);
8902 null_cond = fold_build2_loc (input_location, NE_EXPR,
8903 logical_type_node, src_data,
8904 null_pointer_node);
8906 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
8907 tmp, null_data));
8908 continue;
8911 /* To implement guarded deep copy, i.e., deep copy only allocatable
8912 components that are really allocated, the deep copy code has to
8913 be generated first and then added to the if-block in
8914 gfc_duplicate_allocatable (). */
8915 if (cmp_has_alloc_comps && !c->attr.proc_pointer && !same_type)
8917 rank = c->as ? c->as->rank : 0;
8918 tmp = fold_convert (TREE_TYPE (dcmp), comp);
8919 gfc_add_modify (&fnblock, dcmp, tmp);
8920 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
8921 comp, dcmp,
8922 rank, purpose,
8923 caf_mode);
8925 else
8926 add_when_allocated = NULL_TREE;
8928 if (gfc_deferred_strlen (c, &tmp))
8930 tree len, size;
8931 len = tmp;
8932 tmp = fold_build3_loc (input_location, COMPONENT_REF,
8933 TREE_TYPE (len),
8934 decl, len, NULL_TREE);
8935 len = fold_build3_loc (input_location, COMPONENT_REF,
8936 TREE_TYPE (len),
8937 dest, len, NULL_TREE);
8938 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8939 TREE_TYPE (len), len, tmp);
8940 gfc_add_expr_to_block (&fnblock, tmp);
8941 size = size_of_string_in_bytes (c->ts.kind, len);
8942 /* This component can not have allocatable components,
8943 therefore add_when_allocated of duplicate_allocatable ()
8944 is always NULL. */
8945 tmp = duplicate_allocatable (dcmp, comp, ctype, rank,
8946 false, false, size, NULL_TREE);
8947 gfc_add_expr_to_block (&fnblock, tmp);
8949 else if (c->attr.pdt_array)
8951 tmp = duplicate_allocatable (dcmp, comp, ctype,
8952 c->as ? c->as->rank : 0,
8953 false, false, NULL_TREE, NULL_TREE);
8954 gfc_add_expr_to_block (&fnblock, tmp);
8956 else if ((c->attr.allocatable)
8957 && !c->attr.proc_pointer && !same_type
8958 && (!(cmp_has_alloc_comps && c->as) || c->attr.codimension
8959 || caf_in_coarray (caf_mode)))
8961 rank = c->as ? c->as->rank : 0;
8962 if (c->attr.codimension)
8963 tmp = gfc_copy_allocatable_data (dcmp, comp, ctype, rank);
8964 else if (flag_coarray == GFC_FCOARRAY_LIB
8965 && caf_in_coarray (caf_mode))
8967 tree dst_tok = c->as ? gfc_conv_descriptor_token (dcmp)
8968 : fold_build3_loc (input_location,
8969 COMPONENT_REF,
8970 pvoid_type_node, dest,
8971 c->caf_token,
8972 NULL_TREE);
8973 tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp,
8974 ctype, rank);
8976 else
8977 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank,
8978 add_when_allocated);
8979 gfc_add_expr_to_block (&fnblock, tmp);
8981 else
8982 if (cmp_has_alloc_comps || is_pdt_type)
8983 gfc_add_expr_to_block (&fnblock, add_when_allocated);
8985 break;
8987 case ALLOCATE_PDT_COMP:
8989 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8990 decl, cdecl, NULL_TREE);
8992 /* Set the PDT KIND and LEN fields. */
8993 if (c->attr.pdt_kind || c->attr.pdt_len)
8995 gfc_se tse;
8996 gfc_expr *c_expr = NULL;
8997 gfc_actual_arglist *param = pdt_param_list;
8998 gfc_init_se (&tse, NULL);
8999 for (; param; param = param->next)
9000 if (param->name && !strcmp (c->name, param->name))
9001 c_expr = param->expr;
9003 if (!c_expr)
9004 c_expr = c->initializer;
9006 if (c_expr)
9008 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
9009 gfc_add_modify (&fnblock, comp, tse.expr);
9013 if (c->attr.pdt_string)
9015 gfc_se tse;
9016 gfc_init_se (&tse, NULL);
9017 tree strlen = NULL_TREE;
9018 gfc_expr *e = gfc_copy_expr (c->ts.u.cl->length);
9019 /* Convert the parameterized string length to its value. The
9020 string length is stored in a hidden field in the same way as
9021 deferred string lengths. */
9022 gfc_insert_parameter_exprs (e, pdt_param_list);
9023 if (gfc_deferred_strlen (c, &strlen) && strlen != NULL_TREE)
9025 gfc_conv_expr_type (&tse, e,
9026 TREE_TYPE (strlen));
9027 strlen = fold_build3_loc (input_location, COMPONENT_REF,
9028 TREE_TYPE (strlen),
9029 decl, strlen, NULL_TREE);
9030 gfc_add_modify (&fnblock, strlen, tse.expr);
9031 c->ts.u.cl->backend_decl = strlen;
9033 gfc_free_expr (e);
9035 /* Scalar parameterized strings can be allocated now. */
9036 if (!c->as)
9038 tmp = fold_convert (gfc_array_index_type, strlen);
9039 tmp = size_of_string_in_bytes (c->ts.kind, tmp);
9040 tmp = gfc_evaluate_now (tmp, &fnblock);
9041 tmp = gfc_call_malloc (&fnblock, TREE_TYPE (comp), tmp);
9042 gfc_add_modify (&fnblock, comp, tmp);
9046 /* Allocate parameterized arrays of parameterized derived types. */
9047 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
9048 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9049 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
9050 continue;
9052 if (c->ts.type == BT_CLASS)
9053 comp = gfc_class_data_get (comp);
9055 if (c->attr.pdt_array)
9057 gfc_se tse;
9058 int i;
9059 tree size = gfc_index_one_node;
9060 tree offset = gfc_index_zero_node;
9061 tree lower, upper;
9062 gfc_expr *e;
9064 /* This chunk takes the expressions for 'lower' and 'upper'
9065 in the arrayspec and substitutes in the expressions for
9066 the parameters from 'pdt_param_list'. The descriptor
9067 fields can then be filled from the values so obtained. */
9068 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)));
9069 for (i = 0; i < c->as->rank; i++)
9071 gfc_init_se (&tse, NULL);
9072 e = gfc_copy_expr (c->as->lower[i]);
9073 gfc_insert_parameter_exprs (e, pdt_param_list);
9074 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9075 gfc_free_expr (e);
9076 lower = tse.expr;
9077 gfc_conv_descriptor_lbound_set (&fnblock, comp,
9078 gfc_rank_cst[i],
9079 lower);
9080 e = gfc_copy_expr (c->as->upper[i]);
9081 gfc_insert_parameter_exprs (e, pdt_param_list);
9082 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9083 gfc_free_expr (e);
9084 upper = tse.expr;
9085 gfc_conv_descriptor_ubound_set (&fnblock, comp,
9086 gfc_rank_cst[i],
9087 upper);
9088 gfc_conv_descriptor_stride_set (&fnblock, comp,
9089 gfc_rank_cst[i],
9090 size);
9091 size = gfc_evaluate_now (size, &fnblock);
9092 offset = fold_build2_loc (input_location,
9093 MINUS_EXPR,
9094 gfc_array_index_type,
9095 offset, size);
9096 offset = gfc_evaluate_now (offset, &fnblock);
9097 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9098 gfc_array_index_type,
9099 upper, lower);
9100 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9101 gfc_array_index_type,
9102 tmp, gfc_index_one_node);
9103 size = fold_build2_loc (input_location, MULT_EXPR,
9104 gfc_array_index_type, size, tmp);
9106 gfc_conv_descriptor_offset_set (&fnblock, comp, offset);
9107 if (c->ts.type == BT_CLASS)
9109 tmp = gfc_get_vptr_from_expr (comp);
9110 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
9111 tmp = build_fold_indirect_ref_loc (input_location, tmp);
9112 tmp = gfc_vptr_size_get (tmp);
9114 else
9115 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (ctype));
9116 tmp = fold_convert (gfc_array_index_type, tmp);
9117 size = fold_build2_loc (input_location, MULT_EXPR,
9118 gfc_array_index_type, size, tmp);
9119 size = gfc_evaluate_now (size, &fnblock);
9120 tmp = gfc_call_malloc (&fnblock, NULL, size);
9121 gfc_conv_descriptor_data_set (&fnblock, comp, tmp);
9122 tmp = gfc_conv_descriptor_dtype (comp);
9123 gfc_add_modify (&fnblock, tmp, gfc_get_dtype (ctype));
9125 if (c->initializer && c->initializer->rank)
9127 gfc_init_se (&tse, NULL);
9128 e = gfc_copy_expr (c->initializer);
9129 gfc_insert_parameter_exprs (e, pdt_param_list);
9130 gfc_conv_expr_descriptor (&tse, e);
9131 gfc_add_block_to_block (&fnblock, &tse.pre);
9132 gfc_free_expr (e);
9133 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9134 tmp = build_call_expr_loc (input_location, tmp, 3,
9135 gfc_conv_descriptor_data_get (comp),
9136 gfc_conv_descriptor_data_get (tse.expr),
9137 fold_convert (size_type_node, size));
9138 gfc_add_expr_to_block (&fnblock, tmp);
9139 gfc_add_block_to_block (&fnblock, &tse.post);
9143 /* Recurse in to PDT components. */
9144 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9145 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
9146 && !(c->attr.pointer || c->attr.allocatable))
9148 bool is_deferred = false;
9149 gfc_actual_arglist *tail = c->param_list;
9151 for (; tail; tail = tail->next)
9152 if (!tail->expr)
9153 is_deferred = true;
9155 tail = is_deferred ? pdt_param_list : c->param_list;
9156 tmp = gfc_allocate_pdt_comp (c->ts.u.derived, comp,
9157 c->as ? c->as->rank : 0,
9158 tail);
9159 gfc_add_expr_to_block (&fnblock, tmp);
9162 break;
9164 case DEALLOCATE_PDT_COMP:
9165 /* Deallocate array or parameterized string length components
9166 of parameterized derived types. */
9167 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
9168 && !c->attr.pdt_string
9169 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9170 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
9171 continue;
9173 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9174 decl, cdecl, NULL_TREE);
9175 if (c->ts.type == BT_CLASS)
9176 comp = gfc_class_data_get (comp);
9178 /* Recurse in to PDT components. */
9179 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9180 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
9181 && (!c->attr.pointer && !c->attr.allocatable))
9183 tmp = gfc_deallocate_pdt_comp (c->ts.u.derived, comp,
9184 c->as ? c->as->rank : 0);
9185 gfc_add_expr_to_block (&fnblock, tmp);
9188 if (c->attr.pdt_array)
9190 tmp = gfc_conv_descriptor_data_get (comp);
9191 null_cond = fold_build2_loc (input_location, NE_EXPR,
9192 logical_type_node, tmp,
9193 build_int_cst (TREE_TYPE (tmp), 0));
9194 tmp = gfc_call_free (tmp);
9195 tmp = build3_v (COND_EXPR, null_cond, tmp,
9196 build_empty_stmt (input_location));
9197 gfc_add_expr_to_block (&fnblock, tmp);
9198 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
9200 else if (c->attr.pdt_string)
9202 null_cond = fold_build2_loc (input_location, NE_EXPR,
9203 logical_type_node, comp,
9204 build_int_cst (TREE_TYPE (comp), 0));
9205 tmp = gfc_call_free (comp);
9206 tmp = build3_v (COND_EXPR, null_cond, tmp,
9207 build_empty_stmt (input_location));
9208 gfc_add_expr_to_block (&fnblock, tmp);
9209 tmp = fold_convert (TREE_TYPE (comp), null_pointer_node);
9210 gfc_add_modify (&fnblock, comp, tmp);
9213 break;
9215 case CHECK_PDT_DUMMY:
9217 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9218 decl, cdecl, NULL_TREE);
9219 if (c->ts.type == BT_CLASS)
9220 comp = gfc_class_data_get (comp);
9222 /* Recurse in to PDT components. */
9223 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9224 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type)
9226 tmp = gfc_check_pdt_dummy (c->ts.u.derived, comp,
9227 c->as ? c->as->rank : 0,
9228 pdt_param_list);
9229 gfc_add_expr_to_block (&fnblock, tmp);
9232 if (!c->attr.pdt_len)
9233 continue;
9234 else
9236 gfc_se tse;
9237 gfc_expr *c_expr = NULL;
9238 gfc_actual_arglist *param = pdt_param_list;
9240 gfc_init_se (&tse, NULL);
9241 for (; param; param = param->next)
9242 if (!strcmp (c->name, param->name)
9243 && param->spec_type == SPEC_EXPLICIT)
9244 c_expr = param->expr;
9246 if (c_expr)
9248 tree error, cond, cname;
9249 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
9250 cond = fold_build2_loc (input_location, NE_EXPR,
9251 logical_type_node,
9252 comp, tse.expr);
9253 cname = gfc_build_cstring_const (c->name);
9254 cname = gfc_build_addr_expr (pchar_type_node, cname);
9255 error = gfc_trans_runtime_error (true, NULL,
9256 "The value of the PDT LEN "
9257 "parameter '%s' does not "
9258 "agree with that in the "
9259 "dummy declaration",
9260 cname);
9261 tmp = fold_build3_loc (input_location, COND_EXPR,
9262 void_type_node, cond, error,
9263 build_empty_stmt (input_location));
9264 gfc_add_expr_to_block (&fnblock, tmp);
9267 break;
9269 default:
9270 gcc_unreachable ();
9271 break;
9275 return gfc_finish_block (&fnblock);
9278 /* Recursively traverse an object of derived type, generating code to
9279 nullify allocatable components. */
9281 tree
9282 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
9283 int caf_mode)
9285 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9286 NULLIFY_ALLOC_COMP,
9287 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode);
9291 /* Recursively traverse an object of derived type, generating code to
9292 deallocate allocatable components. */
9294 tree
9295 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
9296 int caf_mode)
9298 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9299 DEALLOCATE_ALLOC_COMP,
9300 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode);
9304 /* Recursively traverse an object of derived type, generating code to
9305 deallocate allocatable components. But do not deallocate coarrays.
9306 To be used for intrinsic assignment, which may not change the allocation
9307 status of coarrays. */
9309 tree
9310 gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank)
9312 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9313 DEALLOCATE_ALLOC_COMP, 0);
9317 tree
9318 gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest)
9320 return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP,
9321 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY);
9325 /* Recursively traverse an object of derived type, generating code to
9326 copy it and its allocatable components. */
9328 tree
9329 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank,
9330 int caf_mode)
9332 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP,
9333 caf_mode);
9337 /* Recursively traverse an object of derived type, generating code to
9338 copy only its allocatable components. */
9340 tree
9341 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
9343 return structure_alloc_comps (der_type, decl, dest, rank,
9344 COPY_ONLY_ALLOC_COMP, 0);
9348 /* Recursively traverse an object of paramterized derived type, generating
9349 code to allocate parameterized components. */
9351 tree
9352 gfc_allocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank,
9353 gfc_actual_arglist *param_list)
9355 tree res;
9356 gfc_actual_arglist *old_param_list = pdt_param_list;
9357 pdt_param_list = param_list;
9358 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9359 ALLOCATE_PDT_COMP, 0);
9360 pdt_param_list = old_param_list;
9361 return res;
9364 /* Recursively traverse an object of paramterized derived type, generating
9365 code to deallocate parameterized components. */
9367 tree
9368 gfc_deallocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank)
9370 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9371 DEALLOCATE_PDT_COMP, 0);
9375 /* Recursively traverse a dummy of paramterized derived type to check the
9376 values of LEN parameters. */
9378 tree
9379 gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, int rank,
9380 gfc_actual_arglist *param_list)
9382 tree res;
9383 gfc_actual_arglist *old_param_list = pdt_param_list;
9384 pdt_param_list = param_list;
9385 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9386 CHECK_PDT_DUMMY, 0);
9387 pdt_param_list = old_param_list;
9388 return res;
9392 /* Returns the value of LBOUND for an expression. This could be broken out
9393 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
9394 called by gfc_alloc_allocatable_for_assignment. */
9395 static tree
9396 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
9398 tree lbound;
9399 tree ubound;
9400 tree stride;
9401 tree cond, cond1, cond3, cond4;
9402 tree tmp;
9403 gfc_ref *ref;
9405 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
9407 tmp = gfc_rank_cst[dim];
9408 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
9409 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
9410 stride = gfc_conv_descriptor_stride_get (desc, tmp);
9411 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
9412 ubound, lbound);
9413 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
9414 stride, gfc_index_zero_node);
9415 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9416 logical_type_node, cond3, cond1);
9417 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
9418 stride, gfc_index_zero_node);
9419 if (assumed_size)
9420 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9421 tmp, build_int_cst (gfc_array_index_type,
9422 expr->rank - 1));
9423 else
9424 cond = logical_false_node;
9426 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
9427 logical_type_node, cond3, cond4);
9428 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
9429 logical_type_node, cond, cond1);
9431 return fold_build3_loc (input_location, COND_EXPR,
9432 gfc_array_index_type, cond,
9433 lbound, gfc_index_one_node);
9436 if (expr->expr_type == EXPR_FUNCTION)
9438 /* A conversion function, so use the argument. */
9439 gcc_assert (expr->value.function.isym
9440 && expr->value.function.isym->conversion);
9441 expr = expr->value.function.actual->expr;
9444 if (expr->expr_type == EXPR_VARIABLE)
9446 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
9447 for (ref = expr->ref; ref; ref = ref->next)
9449 if (ref->type == REF_COMPONENT
9450 && ref->u.c.component->as
9451 && ref->next
9452 && ref->next->u.ar.type == AR_FULL)
9453 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
9455 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
9458 return gfc_index_one_node;
9462 /* Returns true if an expression represents an lhs that can be reallocated
9463 on assignment. */
9465 bool
9466 gfc_is_reallocatable_lhs (gfc_expr *expr)
9468 gfc_ref * ref;
9470 if (!expr->ref)
9471 return false;
9473 /* An allocatable class variable with no reference. */
9474 if (expr->symtree->n.sym->ts.type == BT_CLASS
9475 && CLASS_DATA (expr->symtree->n.sym)->attr.allocatable
9476 && expr->ref && expr->ref->type == REF_COMPONENT
9477 && strcmp (expr->ref->u.c.component->name, "_data") == 0
9478 && expr->ref->next == NULL)
9479 return true;
9481 /* An allocatable variable. */
9482 if (expr->symtree->n.sym->attr.allocatable
9483 && expr->ref
9484 && expr->ref->type == REF_ARRAY
9485 && expr->ref->u.ar.type == AR_FULL)
9486 return true;
9488 /* All that can be left are allocatable components. */
9489 if ((expr->symtree->n.sym->ts.type != BT_DERIVED
9490 && expr->symtree->n.sym->ts.type != BT_CLASS)
9491 || !expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
9492 return false;
9494 /* Find a component ref followed by an array reference. */
9495 for (ref = expr->ref; ref; ref = ref->next)
9496 if (ref->next
9497 && ref->type == REF_COMPONENT
9498 && ref->next->type == REF_ARRAY
9499 && !ref->next->next)
9500 break;
9502 if (!ref)
9503 return false;
9505 /* Return true if valid reallocatable lhs. */
9506 if (ref->u.c.component->attr.allocatable
9507 && ref->next->u.ar.type == AR_FULL)
9508 return true;
9510 return false;
9514 static tree
9515 concat_str_length (gfc_expr* expr)
9517 tree type;
9518 tree len1;
9519 tree len2;
9520 gfc_se se;
9522 type = gfc_typenode_for_spec (&expr->value.op.op1->ts);
9523 len1 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9524 if (len1 == NULL_TREE)
9526 if (expr->value.op.op1->expr_type == EXPR_OP)
9527 len1 = concat_str_length (expr->value.op.op1);
9528 else if (expr->value.op.op1->expr_type == EXPR_CONSTANT)
9529 len1 = build_int_cst (gfc_charlen_type_node,
9530 expr->value.op.op1->value.character.length);
9531 else if (expr->value.op.op1->ts.u.cl->length)
9533 gfc_init_se (&se, NULL);
9534 gfc_conv_expr (&se, expr->value.op.op1->ts.u.cl->length);
9535 len1 = se.expr;
9537 else
9539 /* Last resort! */
9540 gfc_init_se (&se, NULL);
9541 se.want_pointer = 1;
9542 se.descriptor_only = 1;
9543 gfc_conv_expr (&se, expr->value.op.op1);
9544 len1 = se.string_length;
9548 type = gfc_typenode_for_spec (&expr->value.op.op2->ts);
9549 len2 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9550 if (len2 == NULL_TREE)
9552 if (expr->value.op.op2->expr_type == EXPR_OP)
9553 len2 = concat_str_length (expr->value.op.op2);
9554 else if (expr->value.op.op2->expr_type == EXPR_CONSTANT)
9555 len2 = build_int_cst (gfc_charlen_type_node,
9556 expr->value.op.op2->value.character.length);
9557 else if (expr->value.op.op2->ts.u.cl->length)
9559 gfc_init_se (&se, NULL);
9560 gfc_conv_expr (&se, expr->value.op.op2->ts.u.cl->length);
9561 len2 = se.expr;
9563 else
9565 /* Last resort! */
9566 gfc_init_se (&se, NULL);
9567 se.want_pointer = 1;
9568 se.descriptor_only = 1;
9569 gfc_conv_expr (&se, expr->value.op.op2);
9570 len2 = se.string_length;
9574 gcc_assert(len1 && len2);
9575 len1 = fold_convert (gfc_charlen_type_node, len1);
9576 len2 = fold_convert (gfc_charlen_type_node, len2);
9578 return fold_build2_loc (input_location, PLUS_EXPR,
9579 gfc_charlen_type_node, len1, len2);
9583 /* Allocate the lhs of an assignment to an allocatable array, otherwise
9584 reallocate it. */
9586 tree
9587 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
9588 gfc_expr *expr1,
9589 gfc_expr *expr2)
9591 stmtblock_t realloc_block;
9592 stmtblock_t alloc_block;
9593 stmtblock_t fblock;
9594 gfc_ss *rss;
9595 gfc_ss *lss;
9596 gfc_array_info *linfo;
9597 tree realloc_expr;
9598 tree alloc_expr;
9599 tree size1;
9600 tree size2;
9601 tree array1;
9602 tree cond_null;
9603 tree cond;
9604 tree tmp;
9605 tree tmp2;
9606 tree lbound;
9607 tree ubound;
9608 tree desc;
9609 tree old_desc;
9610 tree desc2;
9611 tree offset;
9612 tree jump_label1;
9613 tree jump_label2;
9614 tree neq_size;
9615 tree lbd;
9616 int n;
9617 int dim;
9618 gfc_array_spec * as;
9619 bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
9620 && gfc_caf_attr (expr1, true).codimension);
9621 tree token;
9622 gfc_se caf_se;
9624 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
9625 Find the lhs expression in the loop chain and set expr1 and
9626 expr2 accordingly. */
9627 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
9629 expr2 = expr1;
9630 /* Find the ss for the lhs. */
9631 lss = loop->ss;
9632 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
9633 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
9634 break;
9635 if (lss == gfc_ss_terminator)
9636 return NULL_TREE;
9637 expr1 = lss->info->expr;
9640 /* Bail out if this is not a valid allocate on assignment. */
9641 if (!gfc_is_reallocatable_lhs (expr1)
9642 || (expr2 && !expr2->rank))
9643 return NULL_TREE;
9645 /* Find the ss for the lhs. */
9646 lss = loop->ss;
9647 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
9648 if (lss->info->expr == expr1)
9649 break;
9651 if (lss == gfc_ss_terminator)
9652 return NULL_TREE;
9654 linfo = &lss->info->data.array;
9656 /* Find an ss for the rhs. For operator expressions, we see the
9657 ss's for the operands. Any one of these will do. */
9658 rss = loop->ss;
9659 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
9660 if (rss->info->expr != expr1 && rss != loop->temp_ss)
9661 break;
9663 if (expr2 && rss == gfc_ss_terminator)
9664 return NULL_TREE;
9666 gfc_start_block (&fblock);
9668 /* Since the lhs is allocatable, this must be a descriptor type.
9669 Get the data and array size. */
9670 desc = linfo->descriptor;
9671 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
9672 array1 = gfc_conv_descriptor_data_get (desc);
9674 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
9675 deallocated if expr is an array of different shape or any of the
9676 corresponding length type parameter values of variable and expr
9677 differ." This assures F95 compatibility. */
9678 jump_label1 = gfc_build_label_decl (NULL_TREE);
9679 jump_label2 = gfc_build_label_decl (NULL_TREE);
9681 /* Allocate if data is NULL. */
9682 cond_null = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9683 array1, build_int_cst (TREE_TYPE (array1), 0));
9685 if (expr1->ts.deferred)
9686 cond_null = gfc_evaluate_now (logical_true_node, &fblock);
9687 else
9688 cond_null= gfc_evaluate_now (cond_null, &fblock);
9690 tmp = build3_v (COND_EXPR, cond_null,
9691 build1_v (GOTO_EXPR, jump_label1),
9692 build_empty_stmt (input_location));
9693 gfc_add_expr_to_block (&fblock, tmp);
9695 /* Get arrayspec if expr is a full array. */
9696 if (expr2 && expr2->expr_type == EXPR_FUNCTION
9697 && expr2->value.function.isym
9698 && expr2->value.function.isym->conversion)
9700 /* For conversion functions, take the arg. */
9701 gfc_expr *arg = expr2->value.function.actual->expr;
9702 as = gfc_get_full_arrayspec_from_expr (arg);
9704 else if (expr2)
9705 as = gfc_get_full_arrayspec_from_expr (expr2);
9706 else
9707 as = NULL;
9709 /* If the lhs shape is not the same as the rhs jump to setting the
9710 bounds and doing the reallocation....... */
9711 for (n = 0; n < expr1->rank; n++)
9713 /* Check the shape. */
9714 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
9715 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
9716 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9717 gfc_array_index_type,
9718 loop->to[n], loop->from[n]);
9719 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9720 gfc_array_index_type,
9721 tmp, lbound);
9722 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9723 gfc_array_index_type,
9724 tmp, ubound);
9725 cond = fold_build2_loc (input_location, NE_EXPR,
9726 logical_type_node,
9727 tmp, gfc_index_zero_node);
9728 tmp = build3_v (COND_EXPR, cond,
9729 build1_v (GOTO_EXPR, jump_label1),
9730 build_empty_stmt (input_location));
9731 gfc_add_expr_to_block (&fblock, tmp);
9734 /* ....else jump past the (re)alloc code. */
9735 tmp = build1_v (GOTO_EXPR, jump_label2);
9736 gfc_add_expr_to_block (&fblock, tmp);
9738 /* Add the label to start automatic (re)allocation. */
9739 tmp = build1_v (LABEL_EXPR, jump_label1);
9740 gfc_add_expr_to_block (&fblock, tmp);
9742 /* If the lhs has not been allocated, its bounds will not have been
9743 initialized and so its size is set to zero. */
9744 size1 = gfc_create_var (gfc_array_index_type, NULL);
9745 gfc_init_block (&alloc_block);
9746 gfc_add_modify (&alloc_block, size1, gfc_index_zero_node);
9747 gfc_init_block (&realloc_block);
9748 gfc_add_modify (&realloc_block, size1,
9749 gfc_conv_descriptor_size (desc, expr1->rank));
9750 tmp = build3_v (COND_EXPR, cond_null,
9751 gfc_finish_block (&alloc_block),
9752 gfc_finish_block (&realloc_block));
9753 gfc_add_expr_to_block (&fblock, tmp);
9755 /* Get the rhs size and fix it. */
9756 if (expr2)
9757 desc2 = rss->info->data.array.descriptor;
9758 else
9759 desc2 = NULL_TREE;
9761 size2 = gfc_index_one_node;
9762 for (n = 0; n < expr2->rank; n++)
9764 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9765 gfc_array_index_type,
9766 loop->to[n], loop->from[n]);
9767 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9768 gfc_array_index_type,
9769 tmp, gfc_index_one_node);
9770 size2 = fold_build2_loc (input_location, MULT_EXPR,
9771 gfc_array_index_type,
9772 tmp, size2);
9774 size2 = gfc_evaluate_now (size2, &fblock);
9776 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9777 size1, size2);
9779 /* If the lhs is deferred length, assume that the element size
9780 changes and force a reallocation. */
9781 if (expr1->ts.deferred)
9782 neq_size = gfc_evaluate_now (logical_true_node, &fblock);
9783 else
9784 neq_size = gfc_evaluate_now (cond, &fblock);
9786 /* Deallocation of allocatable components will have to occur on
9787 reallocation. Fix the old descriptor now. */
9788 if ((expr1->ts.type == BT_DERIVED)
9789 && expr1->ts.u.derived->attr.alloc_comp)
9790 old_desc = gfc_evaluate_now (desc, &fblock);
9791 else
9792 old_desc = NULL_TREE;
9794 /* Now modify the lhs descriptor and the associated scalarizer
9795 variables. F2003 7.4.1.3: "If variable is or becomes an
9796 unallocated allocatable variable, then it is allocated with each
9797 deferred type parameter equal to the corresponding type parameters
9798 of expr , with the shape of expr , and with each lower bound equal
9799 to the corresponding element of LBOUND(expr)."
9800 Reuse size1 to keep a dimension-by-dimension track of the
9801 stride of the new array. */
9802 size1 = gfc_index_one_node;
9803 offset = gfc_index_zero_node;
9805 for (n = 0; n < expr2->rank; n++)
9807 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9808 gfc_array_index_type,
9809 loop->to[n], loop->from[n]);
9810 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9811 gfc_array_index_type,
9812 tmp, gfc_index_one_node);
9814 lbound = gfc_index_one_node;
9815 ubound = tmp;
9817 if (as)
9819 lbd = get_std_lbound (expr2, desc2, n,
9820 as->type == AS_ASSUMED_SIZE);
9821 ubound = fold_build2_loc (input_location,
9822 MINUS_EXPR,
9823 gfc_array_index_type,
9824 ubound, lbound);
9825 ubound = fold_build2_loc (input_location,
9826 PLUS_EXPR,
9827 gfc_array_index_type,
9828 ubound, lbd);
9829 lbound = lbd;
9832 gfc_conv_descriptor_lbound_set (&fblock, desc,
9833 gfc_rank_cst[n],
9834 lbound);
9835 gfc_conv_descriptor_ubound_set (&fblock, desc,
9836 gfc_rank_cst[n],
9837 ubound);
9838 gfc_conv_descriptor_stride_set (&fblock, desc,
9839 gfc_rank_cst[n],
9840 size1);
9841 lbound = gfc_conv_descriptor_lbound_get (desc,
9842 gfc_rank_cst[n]);
9843 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
9844 gfc_array_index_type,
9845 lbound, size1);
9846 offset = fold_build2_loc (input_location, MINUS_EXPR,
9847 gfc_array_index_type,
9848 offset, tmp2);
9849 size1 = fold_build2_loc (input_location, MULT_EXPR,
9850 gfc_array_index_type,
9851 tmp, size1);
9854 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
9855 the array offset is saved and the info.offset is used for a
9856 running offset. Use the saved_offset instead. */
9857 tmp = gfc_conv_descriptor_offset (desc);
9858 gfc_add_modify (&fblock, tmp, offset);
9859 if (linfo->saved_offset
9860 && VAR_P (linfo->saved_offset))
9861 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
9863 /* Now set the deltas for the lhs. */
9864 for (n = 0; n < expr1->rank; n++)
9866 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
9867 dim = lss->dim[n];
9868 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9869 gfc_array_index_type, tmp,
9870 loop->from[dim]);
9871 if (linfo->delta[dim] && VAR_P (linfo->delta[dim]))
9872 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
9875 /* Get the new lhs size in bytes. */
9876 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
9878 if (expr2->ts.deferred)
9880 if (VAR_P (expr2->ts.u.cl->backend_decl))
9881 tmp = expr2->ts.u.cl->backend_decl;
9882 else
9883 tmp = rss->info->string_length;
9885 else
9887 tmp = expr2->ts.u.cl->backend_decl;
9888 if (!tmp && expr2->expr_type == EXPR_OP
9889 && expr2->value.op.op == INTRINSIC_CONCAT)
9891 tmp = concat_str_length (expr2);
9892 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
9894 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
9897 if (expr1->ts.u.cl->backend_decl
9898 && VAR_P (expr1->ts.u.cl->backend_decl))
9899 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
9900 else
9901 gfc_add_modify (&fblock, lss->info->string_length, tmp);
9903 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
9905 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
9906 tmp = fold_build2_loc (input_location, MULT_EXPR,
9907 gfc_array_index_type, tmp,
9908 expr1->ts.u.cl->backend_decl);
9910 else
9911 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
9912 tmp = fold_convert (gfc_array_index_type, tmp);
9913 size2 = fold_build2_loc (input_location, MULT_EXPR,
9914 gfc_array_index_type,
9915 tmp, size2);
9916 size2 = fold_convert (size_type_node, size2);
9917 size2 = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
9918 size2, size_one_node);
9919 size2 = gfc_evaluate_now (size2, &fblock);
9921 /* For deferred character length, the 'size' field of the dtype might
9922 have changed so set the dtype. */
9923 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
9924 && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
9926 tree type;
9927 tmp = gfc_conv_descriptor_dtype (desc);
9928 if (expr2->ts.u.cl->backend_decl)
9929 type = gfc_typenode_for_spec (&expr2->ts);
9930 else
9931 type = gfc_typenode_for_spec (&expr1->ts);
9933 gfc_add_modify (&fblock, tmp,
9934 gfc_get_dtype_rank_type (expr1->rank,type));
9936 else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
9938 gfc_add_modify (&fblock, gfc_conv_descriptor_dtype (desc),
9939 gfc_get_dtype (TREE_TYPE (desc)));
9942 /* Realloc expression. Note that the scalarizer uses desc.data
9943 in the array reference - (*desc.data)[<element>]. */
9944 gfc_init_block (&realloc_block);
9945 gfc_init_se (&caf_se, NULL);
9947 if (coarray)
9949 token = gfc_get_ultimate_alloc_ptr_comps_caf_token (&caf_se, expr1);
9950 if (token == NULL_TREE)
9952 tmp = gfc_get_tree_for_caf_expr (expr1);
9953 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
9954 tmp = build_fold_indirect_ref (tmp);
9955 gfc_get_caf_token_offset (&caf_se, &token, NULL, tmp, NULL_TREE,
9956 expr1);
9957 token = gfc_build_addr_expr (NULL_TREE, token);
9960 gfc_add_block_to_block (&realloc_block, &caf_se.pre);
9962 if ((expr1->ts.type == BT_DERIVED)
9963 && expr1->ts.u.derived->attr.alloc_comp)
9965 tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc,
9966 expr1->rank);
9967 gfc_add_expr_to_block (&realloc_block, tmp);
9970 if (!coarray)
9972 tmp = build_call_expr_loc (input_location,
9973 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
9974 fold_convert (pvoid_type_node, array1),
9975 size2);
9976 gfc_conv_descriptor_data_set (&realloc_block,
9977 desc, tmp);
9979 else
9981 tmp = build_call_expr_loc (input_location,
9982 gfor_fndecl_caf_deregister, 5, token,
9983 build_int_cst (integer_type_node,
9984 GFC_CAF_COARRAY_DEALLOCATE_ONLY),
9985 null_pointer_node, null_pointer_node,
9986 integer_zero_node);
9987 gfc_add_expr_to_block (&realloc_block, tmp);
9988 tmp = build_call_expr_loc (input_location,
9989 gfor_fndecl_caf_register,
9990 7, size2,
9991 build_int_cst (integer_type_node,
9992 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY),
9993 token, gfc_build_addr_expr (NULL_TREE, desc),
9994 null_pointer_node, null_pointer_node,
9995 integer_zero_node);
9996 gfc_add_expr_to_block (&realloc_block, tmp);
9999 if ((expr1->ts.type == BT_DERIVED)
10000 && expr1->ts.u.derived->attr.alloc_comp)
10002 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
10003 expr1->rank);
10004 gfc_add_expr_to_block (&realloc_block, tmp);
10007 gfc_add_block_to_block (&realloc_block, &caf_se.post);
10008 realloc_expr = gfc_finish_block (&realloc_block);
10010 /* Only reallocate if sizes are different. */
10011 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
10012 build_empty_stmt (input_location));
10013 realloc_expr = tmp;
10016 /* Malloc expression. */
10017 gfc_init_block (&alloc_block);
10018 if (!coarray)
10020 tmp = build_call_expr_loc (input_location,
10021 builtin_decl_explicit (BUILT_IN_MALLOC),
10022 1, size2);
10023 gfc_conv_descriptor_data_set (&alloc_block,
10024 desc, tmp);
10026 else
10028 tmp = build_call_expr_loc (input_location,
10029 gfor_fndecl_caf_register,
10030 7, size2,
10031 build_int_cst (integer_type_node,
10032 GFC_CAF_COARRAY_ALLOC),
10033 token, gfc_build_addr_expr (NULL_TREE, desc),
10034 null_pointer_node, null_pointer_node,
10035 integer_zero_node);
10036 gfc_add_expr_to_block (&alloc_block, tmp);
10040 /* We already set the dtype in the case of deferred character
10041 length arrays. */
10042 if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
10043 && ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10044 || coarray)))
10046 tmp = gfc_conv_descriptor_dtype (desc);
10047 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
10050 if ((expr1->ts.type == BT_DERIVED)
10051 && expr1->ts.u.derived->attr.alloc_comp)
10053 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
10054 expr1->rank);
10055 gfc_add_expr_to_block (&alloc_block, tmp);
10057 alloc_expr = gfc_finish_block (&alloc_block);
10059 /* Malloc if not allocated; realloc otherwise. */
10060 tmp = build_int_cst (TREE_TYPE (array1), 0);
10061 cond = fold_build2_loc (input_location, EQ_EXPR,
10062 logical_type_node,
10063 array1, tmp);
10064 tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
10065 gfc_add_expr_to_block (&fblock, tmp);
10067 /* Make sure that the scalarizer data pointer is updated. */
10068 if (linfo->data && VAR_P (linfo->data))
10070 tmp = gfc_conv_descriptor_data_get (desc);
10071 gfc_add_modify (&fblock, linfo->data, tmp);
10074 /* Add the exit label. */
10075 tmp = build1_v (LABEL_EXPR, jump_label2);
10076 gfc_add_expr_to_block (&fblock, tmp);
10078 return gfc_finish_block (&fblock);
10082 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
10083 Do likewise, recursively if necessary, with the allocatable components of
10084 derived types. */
10086 void
10087 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
10089 tree type;
10090 tree tmp;
10091 tree descriptor;
10092 stmtblock_t init;
10093 stmtblock_t cleanup;
10094 locus loc;
10095 int rank;
10096 bool sym_has_alloc_comp, has_finalizer;
10098 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
10099 || sym->ts.type == BT_CLASS)
10100 && sym->ts.u.derived->attr.alloc_comp;
10101 has_finalizer = sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED
10102 ? gfc_is_finalizable (sym->ts.u.derived, NULL) : false;
10104 /* Make sure the frontend gets these right. */
10105 gcc_assert (sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp
10106 || has_finalizer);
10108 gfc_save_backend_locus (&loc);
10109 gfc_set_backend_locus (&sym->declared_at);
10110 gfc_init_block (&init);
10112 gcc_assert (VAR_P (sym->backend_decl)
10113 || TREE_CODE (sym->backend_decl) == PARM_DECL);
10115 if (sym->ts.type == BT_CHARACTER
10116 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
10118 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
10119 gfc_trans_vla_type_sizes (sym, &init);
10122 /* Dummy, use associated and result variables don't need anything special. */
10123 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
10125 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
10126 gfc_restore_backend_locus (&loc);
10127 return;
10130 descriptor = sym->backend_decl;
10132 /* Although static, derived types with default initializers and
10133 allocatable components must not be nulled wholesale; instead they
10134 are treated component by component. */
10135 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp && !has_finalizer)
10137 /* SAVEd variables are not freed on exit. */
10138 gfc_trans_static_array_pointer (sym);
10140 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
10141 gfc_restore_backend_locus (&loc);
10142 return;
10145 /* Get the descriptor type. */
10146 type = TREE_TYPE (sym->backend_decl);
10148 if ((sym_has_alloc_comp || (has_finalizer && sym->ts.type != BT_CLASS))
10149 && !(sym->attr.pointer || sym->attr.allocatable))
10151 if (!sym->attr.save
10152 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
10154 if (sym->value == NULL
10155 || !gfc_has_default_initializer (sym->ts.u.derived))
10157 rank = sym->as ? sym->as->rank : 0;
10158 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
10159 descriptor, rank);
10160 gfc_add_expr_to_block (&init, tmp);
10162 else
10163 gfc_init_default_dt (sym, &init, false);
10166 else if (!GFC_DESCRIPTOR_TYPE_P (type))
10168 /* If the backend_decl is not a descriptor, we must have a pointer
10169 to one. */
10170 descriptor = build_fold_indirect_ref_loc (input_location,
10171 sym->backend_decl);
10172 type = TREE_TYPE (descriptor);
10175 /* NULLIFY the data pointer, for non-saved allocatables. */
10176 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save && sym->attr.allocatable)
10178 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
10179 if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
10181 /* Declare the variable static so its array descriptor stays present
10182 after leaving the scope. It may still be accessed through another
10183 image. This may happen, for example, with the caf_mpi
10184 implementation. */
10185 TREE_STATIC (descriptor) = 1;
10186 tmp = gfc_conv_descriptor_token (descriptor);
10187 gfc_add_modify (&init, tmp, fold_convert (TREE_TYPE (tmp),
10188 null_pointer_node));
10192 gfc_restore_backend_locus (&loc);
10193 gfc_init_block (&cleanup);
10195 /* Allocatable arrays need to be freed when they go out of scope.
10196 The allocatable components of pointers must not be touched. */
10197 if (!sym->attr.allocatable && has_finalizer && sym->ts.type != BT_CLASS
10198 && !sym->attr.pointer && !sym->attr.artificial && !sym->attr.save
10199 && !sym->ns->proc_name->attr.is_main_program)
10201 gfc_expr *e;
10202 sym->attr.referenced = 1;
10203 e = gfc_lval_expr_from_sym (sym);
10204 gfc_add_finalizer_call (&cleanup, e);
10205 gfc_free_expr (e);
10207 else if ((!sym->attr.allocatable || !has_finalizer)
10208 && sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
10209 && !sym->attr.pointer && !sym->attr.save
10210 && !sym->ns->proc_name->attr.is_main_program)
10212 int rank;
10213 rank = sym->as ? sym->as->rank : 0;
10214 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
10215 gfc_add_expr_to_block (&cleanup, tmp);
10218 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
10219 && !sym->attr.save && !sym->attr.result
10220 && !sym->ns->proc_name->attr.is_main_program)
10222 gfc_expr *e;
10223 e = has_finalizer ? gfc_lval_expr_from_sym (sym) : NULL;
10224 tmp = gfc_deallocate_with_status (sym->backend_decl, NULL_TREE, NULL_TREE,
10225 NULL_TREE, NULL_TREE, true, e,
10226 sym->attr.codimension
10227 ? GFC_CAF_COARRAY_DEREGISTER
10228 : GFC_CAF_COARRAY_NOCOARRAY);
10229 if (e)
10230 gfc_free_expr (e);
10231 gfc_add_expr_to_block (&cleanup, tmp);
10234 gfc_add_init_cleanup (block, gfc_finish_block (&init),
10235 gfc_finish_block (&cleanup));
10238 /************ Expression Walking Functions ******************/
10240 /* Walk a variable reference.
10242 Possible extension - multiple component subscripts.
10243 x(:,:) = foo%a(:)%b(:)
10244 Transforms to
10245 forall (i=..., j=...)
10246 x(i,j) = foo%a(j)%b(i)
10247 end forall
10248 This adds a fair amount of complexity because you need to deal with more
10249 than one ref. Maybe handle in a similar manner to vector subscripts.
10250 Maybe not worth the effort. */
10253 static gfc_ss *
10254 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
10256 gfc_ref *ref;
10258 for (ref = expr->ref; ref; ref = ref->next)
10259 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
10260 break;
10262 return gfc_walk_array_ref (ss, expr, ref);
10266 gfc_ss *
10267 gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
10269 gfc_array_ref *ar;
10270 gfc_ss *newss;
10271 int n;
10273 for (; ref; ref = ref->next)
10275 if (ref->type == REF_SUBSTRING)
10277 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
10278 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
10281 /* We're only interested in array sections from now on. */
10282 if (ref->type != REF_ARRAY)
10283 continue;
10285 ar = &ref->u.ar;
10287 switch (ar->type)
10289 case AR_ELEMENT:
10290 for (n = ar->dimen - 1; n >= 0; n--)
10291 ss = gfc_get_scalar_ss (ss, ar->start[n]);
10292 break;
10294 case AR_FULL:
10295 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
10296 newss->info->data.array.ref = ref;
10298 /* Make sure array is the same as array(:,:), this way
10299 we don't need to special case all the time. */
10300 ar->dimen = ar->as->rank;
10301 for (n = 0; n < ar->dimen; n++)
10303 ar->dimen_type[n] = DIMEN_RANGE;
10305 gcc_assert (ar->start[n] == NULL);
10306 gcc_assert (ar->end[n] == NULL);
10307 gcc_assert (ar->stride[n] == NULL);
10309 ss = newss;
10310 break;
10312 case AR_SECTION:
10313 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
10314 newss->info->data.array.ref = ref;
10316 /* We add SS chains for all the subscripts in the section. */
10317 for (n = 0; n < ar->dimen; n++)
10319 gfc_ss *indexss;
10321 switch (ar->dimen_type[n])
10323 case DIMEN_ELEMENT:
10324 /* Add SS for elemental (scalar) subscripts. */
10325 gcc_assert (ar->start[n]);
10326 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
10327 indexss->loop_chain = gfc_ss_terminator;
10328 newss->info->data.array.subscript[n] = indexss;
10329 break;
10331 case DIMEN_RANGE:
10332 /* We don't add anything for sections, just remember this
10333 dimension for later. */
10334 newss->dim[newss->dimen] = n;
10335 newss->dimen++;
10336 break;
10338 case DIMEN_VECTOR:
10339 /* Create a GFC_SS_VECTOR index in which we can store
10340 the vector's descriptor. */
10341 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
10342 1, GFC_SS_VECTOR);
10343 indexss->loop_chain = gfc_ss_terminator;
10344 newss->info->data.array.subscript[n] = indexss;
10345 newss->dim[newss->dimen] = n;
10346 newss->dimen++;
10347 break;
10349 default:
10350 /* We should know what sort of section it is by now. */
10351 gcc_unreachable ();
10354 /* We should have at least one non-elemental dimension,
10355 unless we are creating a descriptor for a (scalar) coarray. */
10356 gcc_assert (newss->dimen > 0
10357 || newss->info->data.array.ref->u.ar.as->corank > 0);
10358 ss = newss;
10359 break;
10361 default:
10362 /* We should know what sort of section it is by now. */
10363 gcc_unreachable ();
10367 return ss;
10371 /* Walk an expression operator. If only one operand of a binary expression is
10372 scalar, we must also add the scalar term to the SS chain. */
10374 static gfc_ss *
10375 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
10377 gfc_ss *head;
10378 gfc_ss *head2;
10380 head = gfc_walk_subexpr (ss, expr->value.op.op1);
10381 if (expr->value.op.op2 == NULL)
10382 head2 = head;
10383 else
10384 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
10386 /* All operands are scalar. Pass back and let the caller deal with it. */
10387 if (head2 == ss)
10388 return head2;
10390 /* All operands require scalarization. */
10391 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
10392 return head2;
10394 /* One of the operands needs scalarization, the other is scalar.
10395 Create a gfc_ss for the scalar expression. */
10396 if (head == ss)
10398 /* First operand is scalar. We build the chain in reverse order, so
10399 add the scalar SS after the second operand. */
10400 head = head2;
10401 while (head && head->next != ss)
10402 head = head->next;
10403 /* Check we haven't somehow broken the chain. */
10404 gcc_assert (head);
10405 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
10407 else /* head2 == head */
10409 gcc_assert (head2 == head);
10410 /* Second operand is scalar. */
10411 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
10414 return head2;
10418 /* Reverse a SS chain. */
10420 gfc_ss *
10421 gfc_reverse_ss (gfc_ss * ss)
10423 gfc_ss *next;
10424 gfc_ss *head;
10426 gcc_assert (ss != NULL);
10428 head = gfc_ss_terminator;
10429 while (ss != gfc_ss_terminator)
10431 next = ss->next;
10432 /* Check we didn't somehow break the chain. */
10433 gcc_assert (next != NULL);
10434 ss->next = head;
10435 head = ss;
10436 ss = next;
10439 return (head);
10443 /* Given an expression referring to a procedure, return the symbol of its
10444 interface. We can't get the procedure symbol directly as we have to handle
10445 the case of (deferred) type-bound procedures. */
10447 gfc_symbol *
10448 gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
10450 gfc_symbol *sym;
10451 gfc_ref *ref;
10453 if (procedure_ref == NULL)
10454 return NULL;
10456 /* Normal procedure case. */
10457 if (procedure_ref->expr_type == EXPR_FUNCTION
10458 && procedure_ref->value.function.esym)
10459 sym = procedure_ref->value.function.esym;
10460 else
10461 sym = procedure_ref->symtree->n.sym;
10463 /* Typebound procedure case. */
10464 for (ref = procedure_ref->ref; ref; ref = ref->next)
10466 if (ref->type == REF_COMPONENT
10467 && ref->u.c.component->attr.proc_pointer)
10468 sym = ref->u.c.component->ts.interface;
10469 else
10470 sym = NULL;
10473 return sym;
10477 /* Walk the arguments of an elemental function.
10478 PROC_EXPR is used to check whether an argument is permitted to be absent. If
10479 it is NULL, we don't do the check and the argument is assumed to be present.
10482 gfc_ss *
10483 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
10484 gfc_symbol *proc_ifc, gfc_ss_type type)
10486 gfc_formal_arglist *dummy_arg;
10487 int scalar;
10488 gfc_ss *head;
10489 gfc_ss *tail;
10490 gfc_ss *newss;
10492 head = gfc_ss_terminator;
10493 tail = NULL;
10495 if (proc_ifc)
10496 dummy_arg = gfc_sym_get_dummy_args (proc_ifc);
10497 else
10498 dummy_arg = NULL;
10500 scalar = 1;
10501 for (; arg; arg = arg->next)
10503 if (!arg->expr || arg->expr->expr_type == EXPR_NULL)
10504 goto loop_continue;
10506 newss = gfc_walk_subexpr (head, arg->expr);
10507 if (newss == head)
10509 /* Scalar argument. */
10510 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
10511 newss = gfc_get_scalar_ss (head, arg->expr);
10512 newss->info->type = type;
10513 if (dummy_arg)
10514 newss->info->data.scalar.dummy_arg = dummy_arg->sym;
10516 else
10517 scalar = 0;
10519 if (dummy_arg != NULL
10520 && dummy_arg->sym->attr.optional
10521 && arg->expr->expr_type == EXPR_VARIABLE
10522 && (gfc_expr_attr (arg->expr).optional
10523 || gfc_expr_attr (arg->expr).allocatable
10524 || gfc_expr_attr (arg->expr).pointer))
10525 newss->info->can_be_null_ref = true;
10527 head = newss;
10528 if (!tail)
10530 tail = head;
10531 while (tail->next != gfc_ss_terminator)
10532 tail = tail->next;
10535 loop_continue:
10536 if (dummy_arg != NULL)
10537 dummy_arg = dummy_arg->next;
10540 if (scalar)
10542 /* If all the arguments are scalar we don't need the argument SS. */
10543 gfc_free_ss_chain (head);
10544 /* Pass it back. */
10545 return ss;
10548 /* Add it onto the existing chain. */
10549 tail->next = ss;
10550 return head;
10554 /* Walk a function call. Scalar functions are passed back, and taken out of
10555 scalarization loops. For elemental functions we walk their arguments.
10556 The result of functions returning arrays is stored in a temporary outside
10557 the loop, so that the function is only called once. Hence we do not need
10558 to walk their arguments. */
10560 static gfc_ss *
10561 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
10563 gfc_intrinsic_sym *isym;
10564 gfc_symbol *sym;
10565 gfc_component *comp = NULL;
10567 isym = expr->value.function.isym;
10569 /* Handle intrinsic functions separately. */
10570 if (isym)
10571 return gfc_walk_intrinsic_function (ss, expr, isym);
10573 sym = expr->value.function.esym;
10574 if (!sym)
10575 sym = expr->symtree->n.sym;
10577 if (gfc_is_class_array_function (expr))
10578 return gfc_get_array_ss (ss, expr,
10579 CLASS_DATA (expr->value.function.esym->result)->as->rank,
10580 GFC_SS_FUNCTION);
10582 /* A function that returns arrays. */
10583 comp = gfc_get_proc_ptr_comp (expr);
10584 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
10585 || (comp && comp->attr.dimension))
10586 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
10588 /* Walk the parameters of an elemental function. For now we always pass
10589 by reference. */
10590 if (sym->attr.elemental || (comp && comp->attr.elemental))
10592 gfc_ss *old_ss = ss;
10594 ss = gfc_walk_elemental_function_args (old_ss,
10595 expr->value.function.actual,
10596 gfc_get_proc_ifc_for_expr (expr),
10597 GFC_SS_REFERENCE);
10598 if (ss != old_ss
10599 && (comp
10600 || sym->attr.proc_pointer
10601 || sym->attr.if_source != IFSRC_DECL
10602 || sym->attr.array_outer_dependency))
10603 ss->info->array_outer_dependency = 1;
10606 /* Scalar functions are OK as these are evaluated outside the scalarization
10607 loop. Pass back and let the caller deal with it. */
10608 return ss;
10612 /* An array temporary is constructed for array constructors. */
10614 static gfc_ss *
10615 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
10617 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
10621 /* Walk an expression. Add walked expressions to the head of the SS chain.
10622 A wholly scalar expression will not be added. */
10624 gfc_ss *
10625 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
10627 gfc_ss *head;
10629 switch (expr->expr_type)
10631 case EXPR_VARIABLE:
10632 head = gfc_walk_variable_expr (ss, expr);
10633 return head;
10635 case EXPR_OP:
10636 head = gfc_walk_op_expr (ss, expr);
10637 return head;
10639 case EXPR_FUNCTION:
10640 head = gfc_walk_function_expr (ss, expr);
10641 return head;
10643 case EXPR_CONSTANT:
10644 case EXPR_NULL:
10645 case EXPR_STRUCTURE:
10646 /* Pass back and let the caller deal with it. */
10647 break;
10649 case EXPR_ARRAY:
10650 head = gfc_walk_array_constructor (ss, expr);
10651 return head;
10653 case EXPR_SUBSTRING:
10654 /* Pass back and let the caller deal with it. */
10655 break;
10657 default:
10658 gfc_internal_error ("bad expression type during walk (%d)",
10659 expr->expr_type);
10661 return ss;
10665 /* Entry point for expression walking.
10666 A return value equal to the passed chain means this is
10667 a scalar expression. It is up to the caller to take whatever action is
10668 necessary to translate these. */
10670 gfc_ss *
10671 gfc_walk_expr (gfc_expr * expr)
10673 gfc_ss *res;
10675 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
10676 return gfc_reverse_ss (res);