2018-06-21 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-array.c
blobf0f5c1b709ee2841174a2aadf49dac453bb45ad5
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
243 && TREE_TYPE (field) == get_dtype_type_node ());
245 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
246 desc, field, NULL_TREE);
249 static tree
250 gfc_conv_descriptor_span (tree desc)
252 tree type;
253 tree field;
255 type = TREE_TYPE (desc);
256 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
258 field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
259 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
261 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
262 desc, field, NULL_TREE);
265 tree
266 gfc_conv_descriptor_span_get (tree desc)
268 return gfc_conv_descriptor_span (desc);
271 void
272 gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc,
273 tree value)
275 tree t = gfc_conv_descriptor_span (desc);
276 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
280 tree
281 gfc_conv_descriptor_rank (tree desc)
283 tree tmp;
284 tree dtype;
286 dtype = gfc_conv_descriptor_dtype (desc);
287 tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_RANK);
288 gcc_assert (tmp!= NULL_TREE
289 && TREE_TYPE (tmp) == signed_char_type_node);
290 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
291 dtype, tmp, NULL_TREE);
295 tree
296 gfc_get_descriptor_dimension (tree desc)
298 tree type, field;
300 type = TREE_TYPE (desc);
301 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
303 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
304 gcc_assert (field != NULL_TREE
305 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
306 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
308 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
309 desc, field, NULL_TREE);
313 static tree
314 gfc_conv_descriptor_dimension (tree desc, tree dim)
316 tree tmp;
318 tmp = gfc_get_descriptor_dimension (desc);
320 return gfc_build_array_ref (tmp, dim, NULL);
324 tree
325 gfc_conv_descriptor_token (tree desc)
327 tree type;
328 tree field;
330 type = TREE_TYPE (desc);
331 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
332 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
333 field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
335 /* Should be a restricted pointer - except in the finalization wrapper. */
336 gcc_assert (field != NULL_TREE
337 && (TREE_TYPE (field) == prvoid_type_node
338 || TREE_TYPE (field) == pvoid_type_node));
340 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
341 desc, field, NULL_TREE);
345 static tree
346 gfc_conv_descriptor_stride (tree desc, tree dim)
348 tree tmp;
349 tree field;
351 tmp = gfc_conv_descriptor_dimension (desc, dim);
352 field = TYPE_FIELDS (TREE_TYPE (tmp));
353 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
354 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
356 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
357 tmp, field, NULL_TREE);
358 return tmp;
361 tree
362 gfc_conv_descriptor_stride_get (tree desc, tree dim)
364 tree type = TREE_TYPE (desc);
365 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
366 if (integer_zerop (dim)
367 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
368 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
369 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
370 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
371 return gfc_index_one_node;
373 return gfc_conv_descriptor_stride (desc, dim);
376 void
377 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
378 tree dim, tree value)
380 tree t = gfc_conv_descriptor_stride (desc, dim);
381 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
384 static tree
385 gfc_conv_descriptor_lbound (tree desc, tree dim)
387 tree tmp;
388 tree field;
390 tmp = gfc_conv_descriptor_dimension (desc, dim);
391 field = TYPE_FIELDS (TREE_TYPE (tmp));
392 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
393 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
395 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
396 tmp, field, NULL_TREE);
397 return tmp;
400 tree
401 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
403 return gfc_conv_descriptor_lbound (desc, dim);
406 void
407 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
408 tree dim, tree value)
410 tree t = gfc_conv_descriptor_lbound (desc, dim);
411 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
414 static tree
415 gfc_conv_descriptor_ubound (tree desc, tree dim)
417 tree tmp;
418 tree field;
420 tmp = gfc_conv_descriptor_dimension (desc, dim);
421 field = TYPE_FIELDS (TREE_TYPE (tmp));
422 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
423 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
425 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
426 tmp, field, NULL_TREE);
427 return tmp;
430 tree
431 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
433 return gfc_conv_descriptor_ubound (desc, dim);
436 void
437 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
438 tree dim, tree value)
440 tree t = gfc_conv_descriptor_ubound (desc, dim);
441 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
444 /* Build a null array descriptor constructor. */
446 tree
447 gfc_build_null_descriptor (tree type)
449 tree field;
450 tree tmp;
452 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
453 gcc_assert (DATA_FIELD == 0);
454 field = TYPE_FIELDS (type);
456 /* Set a NULL data pointer. */
457 tmp = build_constructor_single (type, field, null_pointer_node);
458 TREE_CONSTANT (tmp) = 1;
459 /* All other fields are ignored. */
461 return tmp;
465 /* Modify a descriptor such that the lbound of a given dimension is the value
466 specified. This also updates ubound and offset accordingly. */
468 void
469 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
470 int dim, tree new_lbound)
472 tree offs, ubound, lbound, stride;
473 tree diff, offs_diff;
475 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
477 offs = gfc_conv_descriptor_offset_get (desc);
478 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
479 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
480 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
482 /* Get difference (new - old) by which to shift stuff. */
483 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
484 new_lbound, lbound);
486 /* Shift ubound and offset accordingly. This has to be done before
487 updating the lbound, as they depend on the lbound expression! */
488 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
489 ubound, diff);
490 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
491 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
492 diff, stride);
493 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
494 offs, offs_diff);
495 gfc_conv_descriptor_offset_set (block, desc, offs);
497 /* Finally set lbound to value we want. */
498 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
502 /* Obtain offsets for trans-types.c(gfc_get_array_descr_info). */
504 void
505 gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
506 tree *dtype_off, tree *dim_off,
507 tree *dim_size, tree *stride_suboff,
508 tree *lower_suboff, tree *upper_suboff)
510 tree field;
511 tree type;
513 type = TYPE_MAIN_VARIANT (desc_type);
514 field = gfc_advance_chain (TYPE_FIELDS (type), DATA_FIELD);
515 *data_off = byte_position (field);
516 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
517 *dtype_off = byte_position (field);
518 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
519 *dim_off = byte_position (field);
520 type = TREE_TYPE (TREE_TYPE (field));
521 *dim_size = TYPE_SIZE_UNIT (type);
522 field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
523 *stride_suboff = byte_position (field);
524 field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
525 *lower_suboff = byte_position (field);
526 field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
527 *upper_suboff = byte_position (field);
531 /* Cleanup those #defines. */
533 #undef DATA_FIELD
534 #undef OFFSET_FIELD
535 #undef DTYPE_FIELD
536 #undef SPAN_FIELD
537 #undef DIMENSION_FIELD
538 #undef CAF_TOKEN_FIELD
539 #undef STRIDE_SUBFIELD
540 #undef LBOUND_SUBFIELD
541 #undef UBOUND_SUBFIELD
544 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
545 flags & 1 = Main loop body.
546 flags & 2 = temp copy loop. */
548 void
549 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
551 for (; ss != gfc_ss_terminator; ss = ss->next)
552 ss->info->useflags = flags;
556 /* Free a gfc_ss chain. */
558 void
559 gfc_free_ss_chain (gfc_ss * ss)
561 gfc_ss *next;
563 while (ss != gfc_ss_terminator)
565 gcc_assert (ss != NULL);
566 next = ss->next;
567 gfc_free_ss (ss);
568 ss = next;
573 static void
574 free_ss_info (gfc_ss_info *ss_info)
576 int n;
578 ss_info->refcount--;
579 if (ss_info->refcount > 0)
580 return;
582 gcc_assert (ss_info->refcount == 0);
584 switch (ss_info->type)
586 case GFC_SS_SECTION:
587 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
588 if (ss_info->data.array.subscript[n])
589 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
590 break;
592 default:
593 break;
596 free (ss_info);
600 /* Free a SS. */
602 void
603 gfc_free_ss (gfc_ss * ss)
605 free_ss_info (ss->info);
606 free (ss);
610 /* Creates and initializes an array type gfc_ss struct. */
612 gfc_ss *
613 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
615 gfc_ss *ss;
616 gfc_ss_info *ss_info;
617 int i;
619 ss_info = gfc_get_ss_info ();
620 ss_info->refcount++;
621 ss_info->type = type;
622 ss_info->expr = expr;
624 ss = gfc_get_ss ();
625 ss->info = ss_info;
626 ss->next = next;
627 ss->dimen = dimen;
628 for (i = 0; i < ss->dimen; i++)
629 ss->dim[i] = i;
631 return ss;
635 /* Creates and initializes a temporary type gfc_ss struct. */
637 gfc_ss *
638 gfc_get_temp_ss (tree type, tree string_length, int dimen)
640 gfc_ss *ss;
641 gfc_ss_info *ss_info;
642 int i;
644 ss_info = gfc_get_ss_info ();
645 ss_info->refcount++;
646 ss_info->type = GFC_SS_TEMP;
647 ss_info->string_length = string_length;
648 ss_info->data.temp.type = type;
650 ss = gfc_get_ss ();
651 ss->info = ss_info;
652 ss->next = gfc_ss_terminator;
653 ss->dimen = dimen;
654 for (i = 0; i < ss->dimen; i++)
655 ss->dim[i] = i;
657 return ss;
661 /* Creates and initializes a scalar type gfc_ss struct. */
663 gfc_ss *
664 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
666 gfc_ss *ss;
667 gfc_ss_info *ss_info;
669 ss_info = gfc_get_ss_info ();
670 ss_info->refcount++;
671 ss_info->type = GFC_SS_SCALAR;
672 ss_info->expr = expr;
674 ss = gfc_get_ss ();
675 ss->info = ss_info;
676 ss->next = next;
678 return ss;
682 /* Free all the SS associated with a loop. */
684 void
685 gfc_cleanup_loop (gfc_loopinfo * loop)
687 gfc_loopinfo *loop_next, **ploop;
688 gfc_ss *ss;
689 gfc_ss *next;
691 ss = loop->ss;
692 while (ss != gfc_ss_terminator)
694 gcc_assert (ss != NULL);
695 next = ss->loop_chain;
696 gfc_free_ss (ss);
697 ss = next;
700 /* Remove reference to self in the parent loop. */
701 if (loop->parent)
702 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
703 if (*ploop == loop)
705 *ploop = loop->next;
706 break;
709 /* Free non-freed nested loops. */
710 for (loop = loop->nested; loop; loop = loop_next)
712 loop_next = loop->next;
713 gfc_cleanup_loop (loop);
714 free (loop);
719 static void
720 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
722 int n;
724 for (; ss != gfc_ss_terminator; ss = ss->next)
726 ss->loop = loop;
728 if (ss->info->type == GFC_SS_SCALAR
729 || ss->info->type == GFC_SS_REFERENCE
730 || ss->info->type == GFC_SS_TEMP)
731 continue;
733 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
734 if (ss->info->data.array.subscript[n] != NULL)
735 set_ss_loop (ss->info->data.array.subscript[n], loop);
740 /* Associate a SS chain with a loop. */
742 void
743 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
745 gfc_ss *ss;
746 gfc_loopinfo *nested_loop;
748 if (head == gfc_ss_terminator)
749 return;
751 set_ss_loop (head, loop);
753 ss = head;
754 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
756 if (ss->nested_ss)
758 nested_loop = ss->nested_ss->loop;
760 /* More than one ss can belong to the same loop. Hence, we add the
761 loop to the chain only if it is different from the previously
762 added one, to avoid duplicate nested loops. */
763 if (nested_loop != loop->nested)
765 gcc_assert (nested_loop->parent == NULL);
766 nested_loop->parent = loop;
768 gcc_assert (nested_loop->next == NULL);
769 nested_loop->next = loop->nested;
770 loop->nested = nested_loop;
772 else
773 gcc_assert (nested_loop->parent == loop);
776 if (ss->next == gfc_ss_terminator)
777 ss->loop_chain = loop->ss;
778 else
779 ss->loop_chain = ss->next;
781 gcc_assert (ss == gfc_ss_terminator);
782 loop->ss = head;
786 /* Returns true if the expression is an array pointer. */
788 static bool
789 is_pointer_array (tree expr)
791 if (expr == NULL_TREE
792 || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr))
793 || GFC_CLASS_TYPE_P (TREE_TYPE (expr)))
794 return false;
796 if (TREE_CODE (expr) == VAR_DECL
797 && GFC_DECL_PTR_ARRAY_P (expr))
798 return true;
800 if (TREE_CODE (expr) == PARM_DECL
801 && GFC_DECL_PTR_ARRAY_P (expr))
802 return true;
804 if (TREE_CODE (expr) == INDIRECT_REF
805 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 0)))
806 return true;
808 /* The field declaration is marked as an pointer array. */
809 if (TREE_CODE (expr) == COMPONENT_REF
810 && GFC_DECL_PTR_ARRAY_P (TREE_OPERAND (expr, 1))
811 && !GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
812 return true;
814 return false;
818 /* Return the span of an array. */
820 tree
821 gfc_get_array_span (tree desc, gfc_expr *expr)
823 tree tmp;
825 if (is_pointer_array (desc))
826 /* This will have the span field set. */
827 tmp = gfc_conv_descriptor_span_get (desc);
828 else if (TREE_CODE (desc) == COMPONENT_REF
829 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
830 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
832 /* The descriptor is a class _data field and so use the vtable
833 size for the receiving span field. */
834 tmp = gfc_get_vptr_from_expr (desc);
835 tmp = gfc_vptr_size_get (tmp);
837 else if (expr && expr->expr_type == EXPR_VARIABLE
838 && expr->symtree->n.sym->ts.type == BT_CLASS
839 && expr->ref->type == REF_COMPONENT
840 && expr->ref->next->type == REF_ARRAY
841 && expr->ref->next->next == NULL
842 && CLASS_DATA (expr->symtree->n.sym)->attr.dimension)
844 /* Dummys come in sometimes with the descriptor detached from
845 the class field or declaration. */
846 tmp = gfc_class_vptr_get (expr->symtree->n.sym->backend_decl);
847 tmp = gfc_vptr_size_get (tmp);
849 else
851 /* If none of the fancy stuff works, the span is the element
852 size of the array. */
853 tmp = gfc_get_element_type (TREE_TYPE (desc));
854 tmp = fold_convert (gfc_array_index_type,
855 size_in_bytes (tmp));
857 return tmp;
861 /* Generate an initializer for a static pointer or allocatable array. */
863 void
864 gfc_trans_static_array_pointer (gfc_symbol * sym)
866 tree type;
868 gcc_assert (TREE_STATIC (sym->backend_decl));
869 /* Just zero the data member. */
870 type = TREE_TYPE (sym->backend_decl);
871 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
875 /* If the bounds of SE's loop have not yet been set, see if they can be
876 determined from array spec AS, which is the array spec of a called
877 function. MAPPING maps the callee's dummy arguments to the values
878 that the caller is passing. Add any initialization and finalization
879 code to SE. */
881 void
882 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
883 gfc_se * se, gfc_array_spec * as)
885 int n, dim, total_dim;
886 gfc_se tmpse;
887 gfc_ss *ss;
888 tree lower;
889 tree upper;
890 tree tmp;
892 total_dim = 0;
894 if (!as || as->type != AS_EXPLICIT)
895 return;
897 for (ss = se->ss; ss; ss = ss->parent)
899 total_dim += ss->loop->dimen;
900 for (n = 0; n < ss->loop->dimen; n++)
902 /* The bound is known, nothing to do. */
903 if (ss->loop->to[n] != NULL_TREE)
904 continue;
906 dim = ss->dim[n];
907 gcc_assert (dim < as->rank);
908 gcc_assert (ss->loop->dimen <= as->rank);
910 /* Evaluate the lower bound. */
911 gfc_init_se (&tmpse, NULL);
912 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
913 gfc_add_block_to_block (&se->pre, &tmpse.pre);
914 gfc_add_block_to_block (&se->post, &tmpse.post);
915 lower = fold_convert (gfc_array_index_type, tmpse.expr);
917 /* ...and the upper bound. */
918 gfc_init_se (&tmpse, NULL);
919 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
920 gfc_add_block_to_block (&se->pre, &tmpse.pre);
921 gfc_add_block_to_block (&se->post, &tmpse.post);
922 upper = fold_convert (gfc_array_index_type, tmpse.expr);
924 /* Set the upper bound of the loop to UPPER - LOWER. */
925 tmp = fold_build2_loc (input_location, MINUS_EXPR,
926 gfc_array_index_type, upper, lower);
927 tmp = gfc_evaluate_now (tmp, &se->pre);
928 ss->loop->to[n] = tmp;
932 gcc_assert (total_dim == as->rank);
936 /* Generate code to allocate an array temporary, or create a variable to
937 hold the data. If size is NULL, zero the descriptor so that the
938 callee will allocate the array. If DEALLOC is true, also generate code to
939 free the array afterwards.
941 If INITIAL is not NULL, it is packed using internal_pack and the result used
942 as data instead of allocating a fresh, unitialized area of memory.
944 Initialization code is added to PRE and finalization code to POST.
945 DYNAMIC is true if the caller may want to extend the array later
946 using realloc. This prevents us from putting the array on the stack. */
948 static void
949 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
950 gfc_array_info * info, tree size, tree nelem,
951 tree initial, bool dynamic, bool dealloc)
953 tree tmp;
954 tree desc;
955 bool onstack;
957 desc = info->descriptor;
958 info->offset = gfc_index_zero_node;
959 if (size == NULL_TREE || integer_zerop (size))
961 /* A callee allocated array. */
962 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
963 onstack = FALSE;
965 else
967 /* Allocate the temporary. */
968 onstack = !dynamic && initial == NULL_TREE
969 && (flag_stack_arrays
970 || gfc_can_put_var_on_stack (size));
972 if (onstack)
974 /* Make a temporary variable to hold the data. */
975 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
976 nelem, gfc_index_one_node);
977 tmp = gfc_evaluate_now (tmp, pre);
978 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
979 tmp);
980 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
981 tmp);
982 tmp = gfc_create_var (tmp, "A");
983 /* If we're here only because of -fstack-arrays we have to
984 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
985 if (!gfc_can_put_var_on_stack (size))
986 gfc_add_expr_to_block (pre,
987 fold_build1_loc (input_location,
988 DECL_EXPR, TREE_TYPE (tmp),
989 tmp));
990 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
991 gfc_conv_descriptor_data_set (pre, desc, tmp);
993 else
995 /* Allocate memory to hold the data or call internal_pack. */
996 if (initial == NULL_TREE)
998 tmp = gfc_call_malloc (pre, NULL, size);
999 tmp = gfc_evaluate_now (tmp, pre);
1001 else
1003 tree packed;
1004 tree source_data;
1005 tree was_packed;
1006 stmtblock_t do_copying;
1008 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
1009 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
1010 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
1011 tmp = gfc_get_element_type (tmp);
1012 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
1013 packed = gfc_create_var (build_pointer_type (tmp), "data");
1015 tmp = build_call_expr_loc (input_location,
1016 gfor_fndecl_in_pack, 1, initial);
1017 tmp = fold_convert (TREE_TYPE (packed), tmp);
1018 gfc_add_modify (pre, packed, tmp);
1020 tmp = build_fold_indirect_ref_loc (input_location,
1021 initial);
1022 source_data = gfc_conv_descriptor_data_get (tmp);
1024 /* internal_pack may return source->data without any allocation
1025 or copying if it is already packed. If that's the case, we
1026 need to allocate and copy manually. */
1028 gfc_start_block (&do_copying);
1029 tmp = gfc_call_malloc (&do_copying, NULL, size);
1030 tmp = fold_convert (TREE_TYPE (packed), tmp);
1031 gfc_add_modify (&do_copying, packed, tmp);
1032 tmp = gfc_build_memcpy_call (packed, source_data, size);
1033 gfc_add_expr_to_block (&do_copying, tmp);
1035 was_packed = fold_build2_loc (input_location, EQ_EXPR,
1036 logical_type_node, packed,
1037 source_data);
1038 tmp = gfc_finish_block (&do_copying);
1039 tmp = build3_v (COND_EXPR, was_packed, tmp,
1040 build_empty_stmt (input_location));
1041 gfc_add_expr_to_block (pre, tmp);
1043 tmp = fold_convert (pvoid_type_node, packed);
1046 gfc_conv_descriptor_data_set (pre, desc, tmp);
1049 info->data = gfc_conv_descriptor_data_get (desc);
1051 /* The offset is zero because we create temporaries with a zero
1052 lower bound. */
1053 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
1055 if (dealloc && !onstack)
1057 /* Free the temporary. */
1058 tmp = gfc_conv_descriptor_data_get (desc);
1059 tmp = gfc_call_free (tmp);
1060 gfc_add_expr_to_block (post, tmp);
1065 /* Get the scalarizer array dimension corresponding to actual array dimension
1066 given by ARRAY_DIM.
1068 For example, if SS represents the array ref a(1,:,:,1), it is a
1069 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
1070 and 1 for ARRAY_DIM=2.
1071 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
1072 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
1073 ARRAY_DIM=3.
1074 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
1075 array. If called on the inner ss, the result would be respectively 0,1,2 for
1076 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
1077 for ARRAY_DIM=1,2. */
1079 static int
1080 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
1082 int array_ref_dim;
1083 int n;
1085 array_ref_dim = 0;
1087 for (; ss; ss = ss->parent)
1088 for (n = 0; n < ss->dimen; n++)
1089 if (ss->dim[n] < array_dim)
1090 array_ref_dim++;
1092 return array_ref_dim;
1096 static gfc_ss *
1097 innermost_ss (gfc_ss *ss)
1099 while (ss->nested_ss != NULL)
1100 ss = ss->nested_ss;
1102 return ss;
1107 /* Get the array reference dimension corresponding to the given loop dimension.
1108 It is different from the true array dimension given by the dim array in
1109 the case of a partial array reference (i.e. a(:,:,1,:) for example)
1110 It is different from the loop dimension in the case of a transposed array.
1113 static int
1114 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
1116 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
1117 ss->dim[loop_dim]);
1121 /* Generate code to create and initialize the descriptor for a temporary
1122 array. This is used for both temporaries needed by the scalarizer, and
1123 functions returning arrays. Adjusts the loop variables to be
1124 zero-based, and calculates the loop bounds for callee allocated arrays.
1125 Allocate the array unless it's callee allocated (we have a callee
1126 allocated array if 'callee_alloc' is true, or if loop->to[n] is
1127 NULL_TREE for any n). Also fills in the descriptor, data and offset
1128 fields of info if known. Returns the size of the array, or NULL for a
1129 callee allocated array.
1131 'eltype' == NULL signals that the temporary should be a class object.
1132 The 'initial' expression is used to obtain the size of the dynamic
1133 type; otherwise the allocation and initialization proceeds as for any
1134 other expression
1136 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
1137 gfc_trans_allocate_array_storage. */
1139 tree
1140 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
1141 tree eltype, tree initial, bool dynamic,
1142 bool dealloc, bool callee_alloc, locus * where)
1144 gfc_loopinfo *loop;
1145 gfc_ss *s;
1146 gfc_array_info *info;
1147 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
1148 tree type;
1149 tree desc;
1150 tree tmp;
1151 tree size;
1152 tree nelem;
1153 tree cond;
1154 tree or_expr;
1155 tree class_expr = NULL_TREE;
1156 int n, dim, tmp_dim;
1157 int total_dim = 0;
1159 /* This signals a class array for which we need the size of the
1160 dynamic type. Generate an eltype and then the class expression. */
1161 if (eltype == NULL_TREE && initial)
1163 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1164 class_expr = build_fold_indirect_ref_loc (input_location, initial);
1165 eltype = TREE_TYPE (class_expr);
1166 eltype = gfc_get_element_type (eltype);
1167 /* Obtain the structure (class) expression. */
1168 class_expr = TREE_OPERAND (class_expr, 0);
1169 gcc_assert (class_expr);
1172 memset (from, 0, sizeof (from));
1173 memset (to, 0, sizeof (to));
1175 info = &ss->info->data.array;
1177 gcc_assert (ss->dimen > 0);
1178 gcc_assert (ss->loop->dimen == ss->dimen);
1180 if (warn_array_temporaries && where)
1181 gfc_warning (OPT_Warray_temporaries,
1182 "Creating array temporary at %L", where);
1184 /* Set the lower bound to zero. */
1185 for (s = ss; s; s = s->parent)
1187 loop = s->loop;
1189 total_dim += loop->dimen;
1190 for (n = 0; n < loop->dimen; n++)
1192 dim = s->dim[n];
1194 /* Callee allocated arrays may not have a known bound yet. */
1195 if (loop->to[n])
1196 loop->to[n] = gfc_evaluate_now (
1197 fold_build2_loc (input_location, MINUS_EXPR,
1198 gfc_array_index_type,
1199 loop->to[n], loop->from[n]),
1200 pre);
1201 loop->from[n] = gfc_index_zero_node;
1203 /* We have just changed the loop bounds, we must clear the
1204 corresponding specloop, so that delta calculation is not skipped
1205 later in gfc_set_delta. */
1206 loop->specloop[n] = NULL;
1208 /* We are constructing the temporary's descriptor based on the loop
1209 dimensions. As the dimensions may be accessed in arbitrary order
1210 (think of transpose) the size taken from the n'th loop may not map
1211 to the n'th dimension of the array. We need to reconstruct loop
1212 infos in the right order before using it to set the descriptor
1213 bounds. */
1214 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1215 from[tmp_dim] = loop->from[n];
1216 to[tmp_dim] = loop->to[n];
1218 info->delta[dim] = gfc_index_zero_node;
1219 info->start[dim] = gfc_index_zero_node;
1220 info->end[dim] = gfc_index_zero_node;
1221 info->stride[dim] = gfc_index_one_node;
1225 /* Initialize the descriptor. */
1226 type =
1227 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1228 GFC_ARRAY_UNKNOWN, true);
1229 desc = gfc_create_var (type, "atmp");
1230 GFC_DECL_PACKED_ARRAY (desc) = 1;
1232 info->descriptor = desc;
1233 size = gfc_index_one_node;
1235 /* Emit a DECL_EXPR for the variable sized array type in
1236 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
1237 sizes works correctly. */
1238 tree arraytype = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (type));
1239 if (! TYPE_NAME (arraytype))
1240 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
1241 NULL_TREE, arraytype);
1242 gfc_add_expr_to_block (pre, build1 (DECL_EXPR,
1243 arraytype, TYPE_NAME (arraytype)));
1245 /* Fill in the array dtype. */
1246 tmp = gfc_conv_descriptor_dtype (desc);
1247 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1250 Fill in the bounds and stride. This is a packed array, so:
1252 size = 1;
1253 for (n = 0; n < rank; n++)
1255 stride[n] = size
1256 delta = ubound[n] + 1 - lbound[n];
1257 size = size * delta;
1259 size = size * sizeof(element);
1262 or_expr = NULL_TREE;
1264 /* If there is at least one null loop->to[n], it is a callee allocated
1265 array. */
1266 for (n = 0; n < total_dim; n++)
1267 if (to[n] == NULL_TREE)
1269 size = NULL_TREE;
1270 break;
1273 if (size == NULL_TREE)
1274 for (s = ss; s; s = s->parent)
1275 for (n = 0; n < s->loop->dimen; n++)
1277 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
1279 /* For a callee allocated array express the loop bounds in terms
1280 of the descriptor fields. */
1281 tmp = fold_build2_loc (input_location,
1282 MINUS_EXPR, gfc_array_index_type,
1283 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1284 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1285 s->loop->to[n] = tmp;
1287 else
1289 for (n = 0; n < total_dim; n++)
1291 /* Store the stride and bound components in the descriptor. */
1292 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1294 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1295 gfc_index_zero_node);
1297 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1299 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1300 gfc_array_index_type,
1301 to[n], gfc_index_one_node);
1303 /* Check whether the size for this dimension is negative. */
1304 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
1305 tmp, gfc_index_zero_node);
1306 cond = gfc_evaluate_now (cond, pre);
1308 if (n == 0)
1309 or_expr = cond;
1310 else
1311 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1312 logical_type_node, or_expr, cond);
1314 size = fold_build2_loc (input_location, MULT_EXPR,
1315 gfc_array_index_type, size, tmp);
1316 size = gfc_evaluate_now (size, pre);
1320 /* Get the size of the array. */
1321 if (size && !callee_alloc)
1323 tree elemsize;
1324 /* If or_expr is true, then the extent in at least one
1325 dimension is zero and the size is set to zero. */
1326 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1327 or_expr, gfc_index_zero_node, size);
1329 nelem = size;
1330 if (class_expr == NULL_TREE)
1331 elemsize = fold_convert (gfc_array_index_type,
1332 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1333 else
1334 elemsize = gfc_class_vtab_size_get (class_expr);
1336 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1337 size, elemsize);
1339 else
1341 nelem = size;
1342 size = NULL_TREE;
1345 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1346 dynamic, dealloc);
1348 while (ss->parent)
1349 ss = ss->parent;
1351 if (ss->dimen > ss->loop->temp_dim)
1352 ss->loop->temp_dim = ss->dimen;
1354 return size;
1358 /* Return the number of iterations in a loop that starts at START,
1359 ends at END, and has step STEP. */
1361 static tree
1362 gfc_get_iteration_count (tree start, tree end, tree step)
1364 tree tmp;
1365 tree type;
1367 type = TREE_TYPE (step);
1368 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1369 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1370 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1371 build_int_cst (type, 1));
1372 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1373 build_int_cst (type, 0));
1374 return fold_convert (gfc_array_index_type, tmp);
1378 /* Extend the data in array DESC by EXTRA elements. */
1380 static void
1381 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1383 tree arg0, arg1;
1384 tree tmp;
1385 tree size;
1386 tree ubound;
1388 if (integer_zerop (extra))
1389 return;
1391 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1393 /* Add EXTRA to the upper bound. */
1394 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1395 ubound, extra);
1396 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1398 /* Get the value of the current data pointer. */
1399 arg0 = gfc_conv_descriptor_data_get (desc);
1401 /* Calculate the new array size. */
1402 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1403 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1404 ubound, gfc_index_one_node);
1405 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1406 fold_convert (size_type_node, tmp),
1407 fold_convert (size_type_node, size));
1409 /* Call the realloc() function. */
1410 tmp = gfc_call_realloc (pblock, arg0, arg1);
1411 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1415 /* Return true if the bounds of iterator I can only be determined
1416 at run time. */
1418 static inline bool
1419 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1421 return (i->start->expr_type != EXPR_CONSTANT
1422 || i->end->expr_type != EXPR_CONSTANT
1423 || i->step->expr_type != EXPR_CONSTANT);
1427 /* Split the size of constructor element EXPR into the sum of two terms,
1428 one of which can be determined at compile time and one of which must
1429 be calculated at run time. Set *SIZE to the former and return true
1430 if the latter might be nonzero. */
1432 static bool
1433 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1435 if (expr->expr_type == EXPR_ARRAY)
1436 return gfc_get_array_constructor_size (size, expr->value.constructor);
1437 else if (expr->rank > 0)
1439 /* Calculate everything at run time. */
1440 mpz_set_ui (*size, 0);
1441 return true;
1443 else
1445 /* A single element. */
1446 mpz_set_ui (*size, 1);
1447 return false;
1452 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1453 of array constructor C. */
1455 static bool
1456 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1458 gfc_constructor *c;
1459 gfc_iterator *i;
1460 mpz_t val;
1461 mpz_t len;
1462 bool dynamic;
1464 mpz_set_ui (*size, 0);
1465 mpz_init (len);
1466 mpz_init (val);
1468 dynamic = false;
1469 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1471 i = c->iterator;
1472 if (i && gfc_iterator_has_dynamic_bounds (i))
1473 dynamic = true;
1474 else
1476 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1477 if (i)
1479 /* Multiply the static part of the element size by the
1480 number of iterations. */
1481 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1482 mpz_fdiv_q (val, val, i->step->value.integer);
1483 mpz_add_ui (val, val, 1);
1484 if (mpz_sgn (val) > 0)
1485 mpz_mul (len, len, val);
1486 else
1487 mpz_set_ui (len, 0);
1489 mpz_add (*size, *size, len);
1492 mpz_clear (len);
1493 mpz_clear (val);
1494 return dynamic;
1498 /* Make sure offset is a variable. */
1500 static void
1501 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1502 tree * offsetvar)
1504 /* We should have already created the offset variable. We cannot
1505 create it here because we may be in an inner scope. */
1506 gcc_assert (*offsetvar != NULL_TREE);
1507 gfc_add_modify (pblock, *offsetvar, *poffset);
1508 *poffset = *offsetvar;
1509 TREE_USED (*offsetvar) = 1;
1513 /* Variables needed for bounds-checking. */
1514 static bool first_len;
1515 static tree first_len_val;
1516 static bool typespec_chararray_ctor;
1518 static void
1519 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1520 tree offset, gfc_se * se, gfc_expr * expr)
1522 tree tmp;
1524 gfc_conv_expr (se, expr);
1526 /* Store the value. */
1527 tmp = build_fold_indirect_ref_loc (input_location,
1528 gfc_conv_descriptor_data_get (desc));
1529 tmp = gfc_build_array_ref (tmp, offset, NULL);
1531 if (expr->ts.type == BT_CHARACTER)
1533 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1534 tree esize;
1536 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1537 esize = fold_convert (gfc_charlen_type_node, esize);
1538 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1539 TREE_TYPE (esize), esize,
1540 build_int_cst (TREE_TYPE (esize),
1541 gfc_character_kinds[i].bit_size / 8));
1543 gfc_conv_string_parameter (se);
1544 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1546 /* The temporary is an array of pointers. */
1547 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1548 gfc_add_modify (&se->pre, tmp, se->expr);
1550 else
1552 /* The temporary is an array of string values. */
1553 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1554 /* We know the temporary and the value will be the same length,
1555 so can use memcpy. */
1556 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1557 se->string_length, se->expr, expr->ts.kind);
1559 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1561 if (first_len)
1563 gfc_add_modify (&se->pre, first_len_val,
1564 fold_convert (TREE_TYPE (first_len_val),
1565 se->string_length));
1566 first_len = false;
1568 else
1570 /* Verify that all constructor elements are of the same
1571 length. */
1572 tree rhs = fold_convert (TREE_TYPE (first_len_val),
1573 se->string_length);
1574 tree cond = fold_build2_loc (input_location, NE_EXPR,
1575 logical_type_node, first_len_val,
1576 rhs);
1577 gfc_trans_runtime_check
1578 (true, false, cond, &se->pre, &expr->where,
1579 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1580 fold_convert (long_integer_type_node, first_len_val),
1581 fold_convert (long_integer_type_node, se->string_length));
1585 else if (GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
1586 && !GFC_CLASS_TYPE_P (gfc_get_element_type (TREE_TYPE (desc))))
1588 /* Assignment of a CLASS array constructor to a derived type array. */
1589 if (expr->expr_type == EXPR_FUNCTION)
1590 se->expr = gfc_evaluate_now (se->expr, pblock);
1591 se->expr = gfc_class_data_get (se->expr);
1592 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
1593 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1594 gfc_add_modify (&se->pre, tmp, se->expr);
1596 else
1598 /* TODO: Should the frontend already have done this conversion? */
1599 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1600 gfc_add_modify (&se->pre, tmp, se->expr);
1603 gfc_add_block_to_block (pblock, &se->pre);
1604 gfc_add_block_to_block (pblock, &se->post);
1608 /* Add the contents of an array to the constructor. DYNAMIC is as for
1609 gfc_trans_array_constructor_value. */
1611 static void
1612 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1613 tree type ATTRIBUTE_UNUSED,
1614 tree desc, gfc_expr * expr,
1615 tree * poffset, tree * offsetvar,
1616 bool dynamic)
1618 gfc_se se;
1619 gfc_ss *ss;
1620 gfc_loopinfo loop;
1621 stmtblock_t body;
1622 tree tmp;
1623 tree size;
1624 int n;
1626 /* We need this to be a variable so we can increment it. */
1627 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1629 gfc_init_se (&se, NULL);
1631 /* Walk the array expression. */
1632 ss = gfc_walk_expr (expr);
1633 gcc_assert (ss != gfc_ss_terminator);
1635 /* Initialize the scalarizer. */
1636 gfc_init_loopinfo (&loop);
1637 gfc_add_ss_to_loop (&loop, ss);
1639 /* Initialize the loop. */
1640 gfc_conv_ss_startstride (&loop);
1641 gfc_conv_loop_setup (&loop, &expr->where);
1643 /* Make sure the constructed array has room for the new data. */
1644 if (dynamic)
1646 /* Set SIZE to the total number of elements in the subarray. */
1647 size = gfc_index_one_node;
1648 for (n = 0; n < loop.dimen; n++)
1650 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1651 gfc_index_one_node);
1652 size = fold_build2_loc (input_location, MULT_EXPR,
1653 gfc_array_index_type, size, tmp);
1656 /* Grow the constructed array by SIZE elements. */
1657 gfc_grow_array (&loop.pre, desc, size);
1660 /* Make the loop body. */
1661 gfc_mark_ss_chain_used (ss, 1);
1662 gfc_start_scalarized_body (&loop, &body);
1663 gfc_copy_loopinfo_to_se (&se, &loop);
1664 se.ss = ss;
1666 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1667 gcc_assert (se.ss == gfc_ss_terminator);
1669 /* Increment the offset. */
1670 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1671 *poffset, gfc_index_one_node);
1672 gfc_add_modify (&body, *poffset, tmp);
1674 /* Finish the loop. */
1675 gfc_trans_scalarizing_loops (&loop, &body);
1676 gfc_add_block_to_block (&loop.pre, &loop.post);
1677 tmp = gfc_finish_block (&loop.pre);
1678 gfc_add_expr_to_block (pblock, tmp);
1680 gfc_cleanup_loop (&loop);
1684 /* Assign the values to the elements of an array constructor. DYNAMIC
1685 is true if descriptor DESC only contains enough data for the static
1686 size calculated by gfc_get_array_constructor_size. When true, memory
1687 for the dynamic parts must be allocated using realloc. */
1689 static void
1690 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1691 tree desc, gfc_constructor_base base,
1692 tree * poffset, tree * offsetvar,
1693 bool dynamic)
1695 tree tmp;
1696 tree start = NULL_TREE;
1697 tree end = NULL_TREE;
1698 tree step = NULL_TREE;
1699 stmtblock_t body;
1700 gfc_se se;
1701 mpz_t size;
1702 gfc_constructor *c;
1704 tree shadow_loopvar = NULL_TREE;
1705 gfc_saved_var saved_loopvar;
1707 mpz_init (size);
1708 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1710 /* If this is an iterator or an array, the offset must be a variable. */
1711 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1712 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1714 /* Shadowing the iterator avoids changing its value and saves us from
1715 keeping track of it. Further, it makes sure that there's always a
1716 backend-decl for the symbol, even if there wasn't one before,
1717 e.g. in the case of an iterator that appears in a specification
1718 expression in an interface mapping. */
1719 if (c->iterator)
1721 gfc_symbol *sym;
1722 tree type;
1724 /* Evaluate loop bounds before substituting the loop variable
1725 in case they depend on it. Such a case is invalid, but it is
1726 not more expensive to do the right thing here.
1727 See PR 44354. */
1728 gfc_init_se (&se, NULL);
1729 gfc_conv_expr_val (&se, c->iterator->start);
1730 gfc_add_block_to_block (pblock, &se.pre);
1731 start = gfc_evaluate_now (se.expr, pblock);
1733 gfc_init_se (&se, NULL);
1734 gfc_conv_expr_val (&se, c->iterator->end);
1735 gfc_add_block_to_block (pblock, &se.pre);
1736 end = gfc_evaluate_now (se.expr, pblock);
1738 gfc_init_se (&se, NULL);
1739 gfc_conv_expr_val (&se, c->iterator->step);
1740 gfc_add_block_to_block (pblock, &se.pre);
1741 step = gfc_evaluate_now (se.expr, pblock);
1743 sym = c->iterator->var->symtree->n.sym;
1744 type = gfc_typenode_for_spec (&sym->ts);
1746 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1747 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1750 gfc_start_block (&body);
1752 if (c->expr->expr_type == EXPR_ARRAY)
1754 /* Array constructors can be nested. */
1755 gfc_trans_array_constructor_value (&body, type, desc,
1756 c->expr->value.constructor,
1757 poffset, offsetvar, dynamic);
1759 else if (c->expr->rank > 0)
1761 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1762 poffset, offsetvar, dynamic);
1764 else
1766 /* This code really upsets the gimplifier so don't bother for now. */
1767 gfc_constructor *p;
1768 HOST_WIDE_INT n;
1769 HOST_WIDE_INT size;
1771 p = c;
1772 n = 0;
1773 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1775 p = gfc_constructor_next (p);
1776 n++;
1778 if (n < 4)
1780 /* Scalar values. */
1781 gfc_init_se (&se, NULL);
1782 gfc_trans_array_ctor_element (&body, desc, *poffset,
1783 &se, c->expr);
1785 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1786 gfc_array_index_type,
1787 *poffset, gfc_index_one_node);
1789 else
1791 /* Collect multiple scalar constants into a constructor. */
1792 vec<constructor_elt, va_gc> *v = NULL;
1793 tree init;
1794 tree bound;
1795 tree tmptype;
1796 HOST_WIDE_INT idx = 0;
1798 p = c;
1799 /* Count the number of consecutive scalar constants. */
1800 while (p && !(p->iterator
1801 || p->expr->expr_type != EXPR_CONSTANT))
1803 gfc_init_se (&se, NULL);
1804 gfc_conv_constant (&se, p->expr);
1806 if (c->expr->ts.type != BT_CHARACTER)
1807 se.expr = fold_convert (type, se.expr);
1808 /* For constant character array constructors we build
1809 an array of pointers. */
1810 else if (POINTER_TYPE_P (type))
1811 se.expr = gfc_build_addr_expr
1812 (gfc_get_pchar_type (p->expr->ts.kind),
1813 se.expr);
1815 CONSTRUCTOR_APPEND_ELT (v,
1816 build_int_cst (gfc_array_index_type,
1817 idx++),
1818 se.expr);
1819 c = p;
1820 p = gfc_constructor_next (p);
1823 bound = size_int (n - 1);
1824 /* Create an array type to hold them. */
1825 tmptype = build_range_type (gfc_array_index_type,
1826 gfc_index_zero_node, bound);
1827 tmptype = build_array_type (type, tmptype);
1829 init = build_constructor (tmptype, v);
1830 TREE_CONSTANT (init) = 1;
1831 TREE_STATIC (init) = 1;
1832 /* Create a static variable to hold the data. */
1833 tmp = gfc_create_var (tmptype, "data");
1834 TREE_STATIC (tmp) = 1;
1835 TREE_CONSTANT (tmp) = 1;
1836 TREE_READONLY (tmp) = 1;
1837 DECL_INITIAL (tmp) = init;
1838 init = tmp;
1840 /* Use BUILTIN_MEMCPY to assign the values. */
1841 tmp = gfc_conv_descriptor_data_get (desc);
1842 tmp = build_fold_indirect_ref_loc (input_location,
1843 tmp);
1844 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1845 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1846 init = gfc_build_addr_expr (NULL_TREE, init);
1848 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1849 bound = build_int_cst (size_type_node, n * size);
1850 tmp = build_call_expr_loc (input_location,
1851 builtin_decl_explicit (BUILT_IN_MEMCPY),
1852 3, tmp, init, bound);
1853 gfc_add_expr_to_block (&body, tmp);
1855 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1856 gfc_array_index_type, *poffset,
1857 build_int_cst (gfc_array_index_type, n));
1859 if (!INTEGER_CST_P (*poffset))
1861 gfc_add_modify (&body, *offsetvar, *poffset);
1862 *poffset = *offsetvar;
1866 /* The frontend should already have done any expansions
1867 at compile-time. */
1868 if (!c->iterator)
1870 /* Pass the code as is. */
1871 tmp = gfc_finish_block (&body);
1872 gfc_add_expr_to_block (pblock, tmp);
1874 else
1876 /* Build the implied do-loop. */
1877 stmtblock_t implied_do_block;
1878 tree cond;
1879 tree exit_label;
1880 tree loopbody;
1881 tree tmp2;
1883 loopbody = gfc_finish_block (&body);
1885 /* Create a new block that holds the implied-do loop. A temporary
1886 loop-variable is used. */
1887 gfc_start_block(&implied_do_block);
1889 /* Initialize the loop. */
1890 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
1892 /* If this array expands dynamically, and the number of iterations
1893 is not constant, we won't have allocated space for the static
1894 part of C->EXPR's size. Do that now. */
1895 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1897 /* Get the number of iterations. */
1898 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1900 /* Get the static part of C->EXPR's size. */
1901 gfc_get_array_constructor_element_size (&size, c->expr);
1902 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1904 /* Grow the array by TMP * TMP2 elements. */
1905 tmp = fold_build2_loc (input_location, MULT_EXPR,
1906 gfc_array_index_type, tmp, tmp2);
1907 gfc_grow_array (&implied_do_block, desc, tmp);
1910 /* Generate the loop body. */
1911 exit_label = gfc_build_label_decl (NULL_TREE);
1912 gfc_start_block (&body);
1914 /* Generate the exit condition. Depending on the sign of
1915 the step variable we have to generate the correct
1916 comparison. */
1917 tmp = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
1918 step, build_int_cst (TREE_TYPE (step), 0));
1919 cond = fold_build3_loc (input_location, COND_EXPR,
1920 logical_type_node, tmp,
1921 fold_build2_loc (input_location, GT_EXPR,
1922 logical_type_node, shadow_loopvar, end),
1923 fold_build2_loc (input_location, LT_EXPR,
1924 logical_type_node, shadow_loopvar, end));
1925 tmp = build1_v (GOTO_EXPR, exit_label);
1926 TREE_USED (exit_label) = 1;
1927 tmp = build3_v (COND_EXPR, cond, tmp,
1928 build_empty_stmt (input_location));
1929 gfc_add_expr_to_block (&body, tmp);
1931 /* The main loop body. */
1932 gfc_add_expr_to_block (&body, loopbody);
1934 /* Increase loop variable by step. */
1935 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1936 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1937 step);
1938 gfc_add_modify (&body, shadow_loopvar, tmp);
1940 /* Finish the loop. */
1941 tmp = gfc_finish_block (&body);
1942 tmp = build1_v (LOOP_EXPR, tmp);
1943 gfc_add_expr_to_block (&implied_do_block, tmp);
1945 /* Add the exit label. */
1946 tmp = build1_v (LABEL_EXPR, exit_label);
1947 gfc_add_expr_to_block (&implied_do_block, tmp);
1949 /* Finish the implied-do loop. */
1950 tmp = gfc_finish_block(&implied_do_block);
1951 gfc_add_expr_to_block(pblock, tmp);
1953 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1956 mpz_clear (size);
1960 /* The array constructor code can create a string length with an operand
1961 in the form of a temporary variable. This variable will retain its
1962 context (current_function_decl). If we store this length tree in a
1963 gfc_charlen structure which is shared by a variable in another
1964 context, the resulting gfc_charlen structure with a variable in a
1965 different context, we could trip the assertion in expand_expr_real_1
1966 when it sees that a variable has been created in one context and
1967 referenced in another.
1969 If this might be the case, we create a new gfc_charlen structure and
1970 link it into the current namespace. */
1972 static void
1973 store_backend_decl (gfc_charlen **clp, tree len, bool force_new_cl)
1975 if (force_new_cl)
1977 gfc_charlen *new_cl = gfc_new_charlen (gfc_current_ns, *clp);
1978 *clp = new_cl;
1980 (*clp)->backend_decl = len;
1983 /* A catch-all to obtain the string length for anything that is not
1984 a substring of non-constant length, a constant, array or variable. */
1986 static void
1987 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1989 gfc_se se;
1991 /* Don't bother if we already know the length is a constant. */
1992 if (*len && INTEGER_CST_P (*len))
1993 return;
1995 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1996 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1998 /* This is easy. */
1999 gfc_conv_const_charlen (e->ts.u.cl);
2000 *len = e->ts.u.cl->backend_decl;
2002 else
2004 /* Otherwise, be brutal even if inefficient. */
2005 gfc_init_se (&se, NULL);
2007 /* No function call, in case of side effects. */
2008 se.no_function_call = 1;
2009 if (e->rank == 0)
2010 gfc_conv_expr (&se, e);
2011 else
2012 gfc_conv_expr_descriptor (&se, e);
2014 /* Fix the value. */
2015 *len = gfc_evaluate_now (se.string_length, &se.pre);
2017 gfc_add_block_to_block (block, &se.pre);
2018 gfc_add_block_to_block (block, &se.post);
2020 store_backend_decl (&e->ts.u.cl, *len, true);
2025 /* Figure out the string length of a variable reference expression.
2026 Used by get_array_ctor_strlen. */
2028 static void
2029 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
2031 gfc_ref *ref;
2032 gfc_typespec *ts;
2033 mpz_t char_len;
2035 /* Don't bother if we already know the length is a constant. */
2036 if (*len && INTEGER_CST_P (*len))
2037 return;
2039 ts = &expr->symtree->n.sym->ts;
2040 for (ref = expr->ref; ref; ref = ref->next)
2042 switch (ref->type)
2044 case REF_ARRAY:
2045 /* Array references don't change the string length. */
2046 break;
2048 case REF_COMPONENT:
2049 /* Use the length of the component. */
2050 ts = &ref->u.c.component->ts;
2051 break;
2053 case REF_SUBSTRING:
2054 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
2055 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
2057 /* Note that this might evaluate expr. */
2058 get_array_ctor_all_strlen (block, expr, len);
2059 return;
2061 mpz_init_set_ui (char_len, 1);
2062 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
2063 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
2064 *len = gfc_conv_mpz_to_tree_type (char_len, gfc_charlen_type_node);
2065 mpz_clear (char_len);
2066 return;
2068 default:
2069 gcc_unreachable ();
2073 *len = ts->u.cl->backend_decl;
2077 /* Figure out the string length of a character array constructor.
2078 If len is NULL, don't calculate the length; this happens for recursive calls
2079 when a sub-array-constructor is an element but not at the first position,
2080 so when we're not interested in the length.
2081 Returns TRUE if all elements are character constants. */
2083 bool
2084 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
2086 gfc_constructor *c;
2087 bool is_const;
2089 is_const = TRUE;
2091 if (gfc_constructor_first (base) == NULL)
2093 if (len)
2094 *len = build_int_cstu (gfc_charlen_type_node, 0);
2095 return is_const;
2098 /* Loop over all constructor elements to find out is_const, but in len we
2099 want to store the length of the first, not the last, element. We can
2100 of course exit the loop as soon as is_const is found to be false. */
2101 for (c = gfc_constructor_first (base);
2102 c && is_const; c = gfc_constructor_next (c))
2104 switch (c->expr->expr_type)
2106 case EXPR_CONSTANT:
2107 if (len && !(*len && INTEGER_CST_P (*len)))
2108 *len = build_int_cstu (gfc_charlen_type_node,
2109 c->expr->value.character.length);
2110 break;
2112 case EXPR_ARRAY:
2113 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
2114 is_const = false;
2115 break;
2117 case EXPR_VARIABLE:
2118 is_const = false;
2119 if (len)
2120 get_array_ctor_var_strlen (block, c->expr, len);
2121 break;
2123 default:
2124 is_const = false;
2125 if (len)
2126 get_array_ctor_all_strlen (block, c->expr, len);
2127 break;
2130 /* After the first iteration, we don't want the length modified. */
2131 len = NULL;
2134 return is_const;
2137 /* Check whether the array constructor C consists entirely of constant
2138 elements, and if so returns the number of those elements, otherwise
2139 return zero. Note, an empty or NULL array constructor returns zero. */
2141 unsigned HOST_WIDE_INT
2142 gfc_constant_array_constructor_p (gfc_constructor_base base)
2144 unsigned HOST_WIDE_INT nelem = 0;
2146 gfc_constructor *c = gfc_constructor_first (base);
2147 while (c)
2149 if (c->iterator
2150 || c->expr->rank > 0
2151 || c->expr->expr_type != EXPR_CONSTANT)
2152 return 0;
2153 c = gfc_constructor_next (c);
2154 nelem++;
2156 return nelem;
2160 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
2161 and the tree type of it's elements, TYPE, return a static constant
2162 variable that is compile-time initialized. */
2164 tree
2165 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
2167 tree tmptype, init, tmp;
2168 HOST_WIDE_INT nelem;
2169 gfc_constructor *c;
2170 gfc_array_spec as;
2171 gfc_se se;
2172 int i;
2173 vec<constructor_elt, va_gc> *v = NULL;
2175 /* First traverse the constructor list, converting the constants
2176 to tree to build an initializer. */
2177 nelem = 0;
2178 c = gfc_constructor_first (expr->value.constructor);
2179 while (c)
2181 gfc_init_se (&se, NULL);
2182 gfc_conv_constant (&se, c->expr);
2183 if (c->expr->ts.type != BT_CHARACTER)
2184 se.expr = fold_convert (type, se.expr);
2185 else if (POINTER_TYPE_P (type))
2186 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2187 se.expr);
2188 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2189 se.expr);
2190 c = gfc_constructor_next (c);
2191 nelem++;
2194 /* Next determine the tree type for the array. We use the gfortran
2195 front-end's gfc_get_nodesc_array_type in order to create a suitable
2196 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2198 memset (&as, 0, sizeof (gfc_array_spec));
2200 as.rank = expr->rank;
2201 as.type = AS_EXPLICIT;
2202 if (!expr->shape)
2204 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2205 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2206 NULL, nelem - 1);
2208 else
2209 for (i = 0; i < expr->rank; i++)
2211 int tmp = (int) mpz_get_si (expr->shape[i]);
2212 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2213 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2214 NULL, tmp - 1);
2217 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
2219 /* as is not needed anymore. */
2220 for (i = 0; i < as.rank + as.corank; i++)
2222 gfc_free_expr (as.lower[i]);
2223 gfc_free_expr (as.upper[i]);
2226 init = build_constructor (tmptype, v);
2228 TREE_CONSTANT (init) = 1;
2229 TREE_STATIC (init) = 1;
2231 tmp = build_decl (input_location, VAR_DECL, create_tmp_var_name ("A"),
2232 tmptype);
2233 DECL_ARTIFICIAL (tmp) = 1;
2234 DECL_IGNORED_P (tmp) = 1;
2235 TREE_STATIC (tmp) = 1;
2236 TREE_CONSTANT (tmp) = 1;
2237 TREE_READONLY (tmp) = 1;
2238 DECL_INITIAL (tmp) = init;
2239 pushdecl (tmp);
2241 return tmp;
2245 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2246 This mostly initializes the scalarizer state info structure with the
2247 appropriate values to directly use the array created by the function
2248 gfc_build_constant_array_constructor. */
2250 static void
2251 trans_constant_array_constructor (gfc_ss * ss, tree type)
2253 gfc_array_info *info;
2254 tree tmp;
2255 int i;
2257 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
2259 info = &ss->info->data.array;
2261 info->descriptor = tmp;
2262 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
2263 info->offset = gfc_index_zero_node;
2265 for (i = 0; i < ss->dimen; i++)
2267 info->delta[i] = gfc_index_zero_node;
2268 info->start[i] = gfc_index_zero_node;
2269 info->end[i] = gfc_index_zero_node;
2270 info->stride[i] = gfc_index_one_node;
2275 static int
2276 get_rank (gfc_loopinfo *loop)
2278 int rank;
2280 rank = 0;
2281 for (; loop; loop = loop->parent)
2282 rank += loop->dimen;
2284 return rank;
2288 /* Helper routine of gfc_trans_array_constructor to determine if the
2289 bounds of the loop specified by LOOP are constant and simple enough
2290 to use with trans_constant_array_constructor. Returns the
2291 iteration count of the loop if suitable, and NULL_TREE otherwise. */
2293 static tree
2294 constant_array_constructor_loop_size (gfc_loopinfo * l)
2296 gfc_loopinfo *loop;
2297 tree size = gfc_index_one_node;
2298 tree tmp;
2299 int i, total_dim;
2301 total_dim = get_rank (l);
2303 for (loop = l; loop; loop = loop->parent)
2305 for (i = 0; i < loop->dimen; i++)
2307 /* If the bounds aren't constant, return NULL_TREE. */
2308 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2309 return NULL_TREE;
2310 if (!integer_zerop (loop->from[i]))
2312 /* Only allow nonzero "from" in one-dimensional arrays. */
2313 if (total_dim != 1)
2314 return NULL_TREE;
2315 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2316 gfc_array_index_type,
2317 loop->to[i], loop->from[i]);
2319 else
2320 tmp = loop->to[i];
2321 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2322 gfc_array_index_type, tmp, gfc_index_one_node);
2323 size = fold_build2_loc (input_location, MULT_EXPR,
2324 gfc_array_index_type, size, tmp);
2328 return size;
2332 static tree *
2333 get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2335 gfc_ss *ss;
2336 int n;
2338 gcc_assert (array->nested_ss == NULL);
2340 for (ss = array; ss; ss = ss->parent)
2341 for (n = 0; n < ss->loop->dimen; n++)
2342 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2343 return &(ss->loop->to[n]);
2345 gcc_unreachable ();
2349 static gfc_loopinfo *
2350 outermost_loop (gfc_loopinfo * loop)
2352 while (loop->parent != NULL)
2353 loop = loop->parent;
2355 return loop;
2359 /* Array constructors are handled by constructing a temporary, then using that
2360 within the scalarization loop. This is not optimal, but seems by far the
2361 simplest method. */
2363 static void
2364 trans_array_constructor (gfc_ss * ss, locus * where)
2366 gfc_constructor_base c;
2367 tree offset;
2368 tree offsetvar;
2369 tree desc;
2370 tree type;
2371 tree tmp;
2372 tree *loop_ubound0;
2373 bool dynamic;
2374 bool old_first_len, old_typespec_chararray_ctor;
2375 tree old_first_len_val;
2376 gfc_loopinfo *loop, *outer_loop;
2377 gfc_ss_info *ss_info;
2378 gfc_expr *expr;
2379 gfc_ss *s;
2380 tree neg_len;
2381 char *msg;
2383 /* Save the old values for nested checking. */
2384 old_first_len = first_len;
2385 old_first_len_val = first_len_val;
2386 old_typespec_chararray_ctor = typespec_chararray_ctor;
2388 loop = ss->loop;
2389 outer_loop = outermost_loop (loop);
2390 ss_info = ss->info;
2391 expr = ss_info->expr;
2393 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2394 typespec was given for the array constructor. */
2395 typespec_chararray_ctor = (expr->ts.type == BT_CHARACTER
2396 && expr->ts.u.cl
2397 && expr->ts.u.cl->length_from_typespec);
2399 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2400 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2402 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2403 first_len = true;
2406 gcc_assert (ss->dimen == ss->loop->dimen);
2408 c = expr->value.constructor;
2409 if (expr->ts.type == BT_CHARACTER)
2411 bool const_string;
2412 bool force_new_cl = false;
2414 /* get_array_ctor_strlen walks the elements of the constructor, if a
2415 typespec was given, we already know the string length and want the one
2416 specified there. */
2417 if (typespec_chararray_ctor && expr->ts.u.cl->length
2418 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2420 gfc_se length_se;
2422 const_string = false;
2423 gfc_init_se (&length_se, NULL);
2424 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2425 gfc_charlen_type_node);
2426 ss_info->string_length = length_se.expr;
2428 /* Check if the character length is negative. If it is, then
2429 set LEN = 0. */
2430 neg_len = fold_build2_loc (input_location, LT_EXPR,
2431 logical_type_node, ss_info->string_length,
2432 build_zero_cst (TREE_TYPE
2433 (ss_info->string_length)));
2434 /* Print a warning if bounds checking is enabled. */
2435 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2437 msg = xasprintf ("Negative character length treated as LEN = 0");
2438 gfc_trans_runtime_check (false, true, neg_len, &length_se.pre,
2439 where, msg);
2440 free (msg);
2443 ss_info->string_length
2444 = fold_build3_loc (input_location, COND_EXPR,
2445 gfc_charlen_type_node, neg_len,
2446 build_zero_cst
2447 (TREE_TYPE (ss_info->string_length)),
2448 ss_info->string_length);
2449 ss_info->string_length = gfc_evaluate_now (ss_info->string_length,
2450 &length_se.pre);
2452 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2453 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2455 else
2457 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2458 &ss_info->string_length);
2459 force_new_cl = true;
2462 /* Complex character array constructors should have been taken care of
2463 and not end up here. */
2464 gcc_assert (ss_info->string_length);
2466 store_backend_decl (&expr->ts.u.cl, ss_info->string_length, force_new_cl);
2468 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2469 if (const_string)
2470 type = build_pointer_type (type);
2472 else
2473 type = gfc_typenode_for_spec (expr->ts.type == BT_CLASS
2474 ? &CLASS_DATA (expr)->ts : &expr->ts);
2476 /* See if the constructor determines the loop bounds. */
2477 dynamic = false;
2479 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2481 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
2483 /* We have a multidimensional parameter. */
2484 for (s = ss; s; s = s->parent)
2486 int n;
2487 for (n = 0; n < s->loop->dimen; n++)
2489 s->loop->from[n] = gfc_index_zero_node;
2490 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2491 gfc_index_integer_kind);
2492 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2493 gfc_array_index_type,
2494 s->loop->to[n],
2495 gfc_index_one_node);
2500 if (*loop_ubound0 == NULL_TREE)
2502 mpz_t size;
2504 /* We should have a 1-dimensional, zero-based loop. */
2505 gcc_assert (loop->parent == NULL && loop->nested == NULL);
2506 gcc_assert (loop->dimen == 1);
2507 gcc_assert (integer_zerop (loop->from[0]));
2509 /* Split the constructor size into a static part and a dynamic part.
2510 Allocate the static size up-front and record whether the dynamic
2511 size might be nonzero. */
2512 mpz_init (size);
2513 dynamic = gfc_get_array_constructor_size (&size, c);
2514 mpz_sub_ui (size, size, 1);
2515 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2516 mpz_clear (size);
2519 /* Special case constant array constructors. */
2520 if (!dynamic)
2522 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2523 if (nelem > 0)
2525 tree size = constant_array_constructor_loop_size (loop);
2526 if (size && compare_tree_int (size, nelem) == 0)
2528 trans_constant_array_constructor (ss, type);
2529 goto finish;
2534 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2535 NULL_TREE, dynamic, true, false, where);
2537 desc = ss_info->data.array.descriptor;
2538 offset = gfc_index_zero_node;
2539 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2540 TREE_NO_WARNING (offsetvar) = 1;
2541 TREE_USED (offsetvar) = 0;
2542 gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
2543 &offset, &offsetvar, dynamic);
2545 /* If the array grows dynamically, the upper bound of the loop variable
2546 is determined by the array's final upper bound. */
2547 if (dynamic)
2549 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2550 gfc_array_index_type,
2551 offsetvar, gfc_index_one_node);
2552 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2553 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2554 if (*loop_ubound0 && VAR_P (*loop_ubound0))
2555 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
2556 else
2557 *loop_ubound0 = tmp;
2560 if (TREE_USED (offsetvar))
2561 pushdecl (offsetvar);
2562 else
2563 gcc_assert (INTEGER_CST_P (offset));
2565 #if 0
2566 /* Disable bound checking for now because it's probably broken. */
2567 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2569 gcc_unreachable ();
2571 #endif
2573 finish:
2574 /* Restore old values of globals. */
2575 first_len = old_first_len;
2576 first_len_val = old_first_len_val;
2577 typespec_chararray_ctor = old_typespec_chararray_ctor;
2581 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2582 called after evaluating all of INFO's vector dimensions. Go through
2583 each such vector dimension and see if we can now fill in any missing
2584 loop bounds. */
2586 static void
2587 set_vector_loop_bounds (gfc_ss * ss)
2589 gfc_loopinfo *loop, *outer_loop;
2590 gfc_array_info *info;
2591 gfc_se se;
2592 tree tmp;
2593 tree desc;
2594 tree zero;
2595 int n;
2596 int dim;
2598 outer_loop = outermost_loop (ss->loop);
2600 info = &ss->info->data.array;
2602 for (; ss; ss = ss->parent)
2604 loop = ss->loop;
2606 for (n = 0; n < loop->dimen; n++)
2608 dim = ss->dim[n];
2609 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2610 || loop->to[n] != NULL)
2611 continue;
2613 /* Loop variable N indexes vector dimension DIM, and we don't
2614 yet know the upper bound of loop variable N. Set it to the
2615 difference between the vector's upper and lower bounds. */
2616 gcc_assert (loop->from[n] == gfc_index_zero_node);
2617 gcc_assert (info->subscript[dim]
2618 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2620 gfc_init_se (&se, NULL);
2621 desc = info->subscript[dim]->info->data.array.descriptor;
2622 zero = gfc_rank_cst[0];
2623 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2624 gfc_array_index_type,
2625 gfc_conv_descriptor_ubound_get (desc, zero),
2626 gfc_conv_descriptor_lbound_get (desc, zero));
2627 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2628 loop->to[n] = tmp;
2634 /* Tells whether a scalar argument to an elemental procedure is saved out
2635 of a scalarization loop as a value or as a reference. */
2637 bool
2638 gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info)
2640 if (ss_info->type != GFC_SS_REFERENCE)
2641 return false;
2643 /* If the actual argument can be absent (in other words, it can
2644 be a NULL reference), don't try to evaluate it; pass instead
2645 the reference directly. */
2646 if (ss_info->can_be_null_ref)
2647 return true;
2649 /* If the expression is of polymorphic type, it's actual size is not known,
2650 so we avoid copying it anywhere. */
2651 if (ss_info->data.scalar.dummy_arg
2652 && ss_info->data.scalar.dummy_arg->ts.type == BT_CLASS
2653 && ss_info->expr->ts.type == BT_CLASS)
2654 return true;
2656 /* If the expression is a data reference of aggregate type,
2657 and the data reference is not used on the left hand side,
2658 avoid a copy by saving a reference to the content. */
2659 if (!ss_info->data.scalar.needs_temporary
2660 && (ss_info->expr->ts.type == BT_DERIVED
2661 || ss_info->expr->ts.type == BT_CLASS)
2662 && gfc_expr_is_variable (ss_info->expr))
2663 return true;
2665 /* Otherwise the expression is evaluated to a temporary variable before the
2666 scalarization loop. */
2667 return false;
2671 /* Add the pre and post chains for all the scalar expressions in a SS chain
2672 to loop. This is called after the loop parameters have been calculated,
2673 but before the actual scalarizing loops. */
2675 static void
2676 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2677 locus * where)
2679 gfc_loopinfo *nested_loop, *outer_loop;
2680 gfc_se se;
2681 gfc_ss_info *ss_info;
2682 gfc_array_info *info;
2683 gfc_expr *expr;
2684 int n;
2686 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
2687 arguments could get evaluated multiple times. */
2688 if (ss->is_alloc_lhs)
2689 return;
2691 outer_loop = outermost_loop (loop);
2693 /* TODO: This can generate bad code if there are ordering dependencies,
2694 e.g., a callee allocated function and an unknown size constructor. */
2695 gcc_assert (ss != NULL);
2697 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2699 gcc_assert (ss);
2701 /* Cross loop arrays are handled from within the most nested loop. */
2702 if (ss->nested_ss != NULL)
2703 continue;
2705 ss_info = ss->info;
2706 expr = ss_info->expr;
2707 info = &ss_info->data.array;
2709 switch (ss_info->type)
2711 case GFC_SS_SCALAR:
2712 /* Scalar expression. Evaluate this now. This includes elemental
2713 dimension indices, but not array section bounds. */
2714 gfc_init_se (&se, NULL);
2715 gfc_conv_expr (&se, expr);
2716 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2718 if (expr->ts.type != BT_CHARACTER
2719 && !gfc_is_alloc_class_scalar_function (expr))
2721 /* Move the evaluation of scalar expressions outside the
2722 scalarization loop, except for WHERE assignments. */
2723 if (subscript)
2724 se.expr = convert(gfc_array_index_type, se.expr);
2725 if (!ss_info->where)
2726 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
2727 gfc_add_block_to_block (&outer_loop->pre, &se.post);
2729 else
2730 gfc_add_block_to_block (&outer_loop->post, &se.post);
2732 ss_info->data.scalar.value = se.expr;
2733 ss_info->string_length = se.string_length;
2734 break;
2736 case GFC_SS_REFERENCE:
2737 /* Scalar argument to elemental procedure. */
2738 gfc_init_se (&se, NULL);
2739 if (gfc_scalar_elemental_arg_saved_as_reference (ss_info))
2740 gfc_conv_expr_reference (&se, expr);
2741 else
2743 /* Evaluate the argument outside the loop and pass
2744 a reference to the value. */
2745 gfc_conv_expr (&se, expr);
2748 /* Ensure that a pointer to the string is stored. */
2749 if (expr->ts.type == BT_CHARACTER)
2750 gfc_conv_string_parameter (&se);
2752 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2753 gfc_add_block_to_block (&outer_loop->post, &se.post);
2754 if (gfc_is_class_scalar_expr (expr))
2755 /* This is necessary because the dynamic type will always be
2756 large than the declared type. In consequence, assigning
2757 the value to a temporary could segfault.
2758 OOP-TODO: see if this is generally correct or is the value
2759 has to be written to an allocated temporary, whose address
2760 is passed via ss_info. */
2761 ss_info->data.scalar.value = se.expr;
2762 else
2763 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
2764 &outer_loop->pre);
2766 ss_info->string_length = se.string_length;
2767 break;
2769 case GFC_SS_SECTION:
2770 /* Add the expressions for scalar and vector subscripts. */
2771 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2772 if (info->subscript[n])
2773 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2775 set_vector_loop_bounds (ss);
2776 break;
2778 case GFC_SS_VECTOR:
2779 /* Get the vector's descriptor and store it in SS. */
2780 gfc_init_se (&se, NULL);
2781 gfc_conv_expr_descriptor (&se, expr);
2782 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2783 gfc_add_block_to_block (&outer_loop->post, &se.post);
2784 info->descriptor = se.expr;
2785 break;
2787 case GFC_SS_INTRINSIC:
2788 gfc_add_intrinsic_ss_code (loop, ss);
2789 break;
2791 case GFC_SS_FUNCTION:
2792 /* Array function return value. We call the function and save its
2793 result in a temporary for use inside the loop. */
2794 gfc_init_se (&se, NULL);
2795 se.loop = loop;
2796 se.ss = ss;
2797 if (gfc_is_class_array_function (expr))
2798 expr->must_finalize = 1;
2799 gfc_conv_expr (&se, expr);
2800 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2801 gfc_add_block_to_block (&outer_loop->post, &se.post);
2802 ss_info->string_length = se.string_length;
2803 break;
2805 case GFC_SS_CONSTRUCTOR:
2806 if (expr->ts.type == BT_CHARACTER
2807 && ss_info->string_length == NULL
2808 && expr->ts.u.cl
2809 && expr->ts.u.cl->length
2810 && expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
2812 gfc_init_se (&se, NULL);
2813 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2814 gfc_charlen_type_node);
2815 ss_info->string_length = se.expr;
2816 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2817 gfc_add_block_to_block (&outer_loop->post, &se.post);
2819 trans_array_constructor (ss, where);
2820 break;
2822 case GFC_SS_TEMP:
2823 case GFC_SS_COMPONENT:
2824 /* Do nothing. These are handled elsewhere. */
2825 break;
2827 default:
2828 gcc_unreachable ();
2832 if (!subscript)
2833 for (nested_loop = loop->nested; nested_loop;
2834 nested_loop = nested_loop->next)
2835 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
2839 /* Translate expressions for the descriptor and data pointer of a SS. */
2840 /*GCC ARRAYS*/
2842 static void
2843 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2845 gfc_se se;
2846 gfc_ss_info *ss_info;
2847 gfc_array_info *info;
2848 tree tmp;
2850 ss_info = ss->info;
2851 info = &ss_info->data.array;
2853 /* Get the descriptor for the array to be scalarized. */
2854 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2855 gfc_init_se (&se, NULL);
2856 se.descriptor_only = 1;
2857 gfc_conv_expr_lhs (&se, ss_info->expr);
2858 gfc_add_block_to_block (block, &se.pre);
2859 info->descriptor = se.expr;
2860 ss_info->string_length = se.string_length;
2862 if (base)
2864 if (ss_info->expr->ts.type == BT_CHARACTER && !ss_info->expr->ts.deferred
2865 && ss_info->expr->ts.u.cl->length == NULL)
2867 /* Emit a DECL_EXPR for the variable sized array type in
2868 GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type
2869 sizes works correctly. */
2870 tree arraytype = TREE_TYPE (
2871 GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (info->descriptor)));
2872 if (! TYPE_NAME (arraytype))
2873 TYPE_NAME (arraytype) = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
2874 NULL_TREE, arraytype);
2875 gfc_add_expr_to_block (block, build1 (DECL_EXPR, arraytype,
2876 TYPE_NAME (arraytype)));
2878 /* Also the data pointer. */
2879 tmp = gfc_conv_array_data (se.expr);
2880 /* If this is a variable or address of a variable we use it directly.
2881 Otherwise we must evaluate it now to avoid breaking dependency
2882 analysis by pulling the expressions for elemental array indices
2883 inside the loop. */
2884 if (!(DECL_P (tmp)
2885 || (TREE_CODE (tmp) == ADDR_EXPR
2886 && DECL_P (TREE_OPERAND (tmp, 0)))))
2887 tmp = gfc_evaluate_now (tmp, block);
2888 info->data = tmp;
2890 tmp = gfc_conv_array_offset (se.expr);
2891 info->offset = gfc_evaluate_now (tmp, block);
2893 /* Make absolutely sure that the saved_offset is indeed saved
2894 so that the variable is still accessible after the loops
2895 are translated. */
2896 info->saved_offset = info->offset;
2901 /* Initialize a gfc_loopinfo structure. */
2903 void
2904 gfc_init_loopinfo (gfc_loopinfo * loop)
2906 int n;
2908 memset (loop, 0, sizeof (gfc_loopinfo));
2909 gfc_init_block (&loop->pre);
2910 gfc_init_block (&loop->post);
2912 /* Initially scalarize in order and default to no loop reversal. */
2913 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2915 loop->order[n] = n;
2916 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2919 loop->ss = gfc_ss_terminator;
2923 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2924 chain. */
2926 void
2927 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2929 se->loop = loop;
2933 /* Return an expression for the data pointer of an array. */
2935 tree
2936 gfc_conv_array_data (tree descriptor)
2938 tree type;
2940 type = TREE_TYPE (descriptor);
2941 if (GFC_ARRAY_TYPE_P (type))
2943 if (TREE_CODE (type) == POINTER_TYPE)
2944 return descriptor;
2945 else
2947 /* Descriptorless arrays. */
2948 return gfc_build_addr_expr (NULL_TREE, descriptor);
2951 else
2952 return gfc_conv_descriptor_data_get (descriptor);
2956 /* Return an expression for the base offset of an array. */
2958 tree
2959 gfc_conv_array_offset (tree descriptor)
2961 tree type;
2963 type = TREE_TYPE (descriptor);
2964 if (GFC_ARRAY_TYPE_P (type))
2965 return GFC_TYPE_ARRAY_OFFSET (type);
2966 else
2967 return gfc_conv_descriptor_offset_get (descriptor);
2971 /* Get an expression for the array stride. */
2973 tree
2974 gfc_conv_array_stride (tree descriptor, int dim)
2976 tree tmp;
2977 tree type;
2979 type = TREE_TYPE (descriptor);
2981 /* For descriptorless arrays use the array size. */
2982 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2983 if (tmp != NULL_TREE)
2984 return tmp;
2986 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2987 return tmp;
2991 /* Like gfc_conv_array_stride, but for the lower bound. */
2993 tree
2994 gfc_conv_array_lbound (tree descriptor, int dim)
2996 tree tmp;
2997 tree type;
2999 type = TREE_TYPE (descriptor);
3001 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
3002 if (tmp != NULL_TREE)
3003 return tmp;
3005 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
3006 return tmp;
3010 /* Like gfc_conv_array_stride, but for the upper bound. */
3012 tree
3013 gfc_conv_array_ubound (tree descriptor, int dim)
3015 tree tmp;
3016 tree type;
3018 type = TREE_TYPE (descriptor);
3020 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
3021 if (tmp != NULL_TREE)
3022 return tmp;
3024 /* This should only ever happen when passing an assumed shape array
3025 as an actual parameter. The value will never be used. */
3026 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
3027 return gfc_index_zero_node;
3029 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
3030 return tmp;
3034 /* Generate code to perform an array index bound check. */
3036 static tree
3037 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
3038 locus * where, bool check_upper)
3040 tree fault;
3041 tree tmp_lo, tmp_up;
3042 tree descriptor;
3043 char *msg;
3044 const char * name = NULL;
3046 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
3047 return index;
3049 descriptor = ss->info->data.array.descriptor;
3051 index = gfc_evaluate_now (index, &se->pre);
3053 /* We find a name for the error message. */
3054 name = ss->info->expr->symtree->n.sym->name;
3055 gcc_assert (name != NULL);
3057 if (VAR_P (descriptor))
3058 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
3060 /* If upper bound is present, include both bounds in the error message. */
3061 if (check_upper)
3063 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3064 tmp_up = gfc_conv_array_ubound (descriptor, n);
3066 if (name)
3067 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3068 "outside of expected range (%%ld:%%ld)", n+1, name);
3069 else
3070 msg = xasprintf ("Index '%%ld' of dimension %d "
3071 "outside of expected range (%%ld:%%ld)", n+1);
3073 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3074 index, tmp_lo);
3075 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3076 fold_convert (long_integer_type_node, index),
3077 fold_convert (long_integer_type_node, tmp_lo),
3078 fold_convert (long_integer_type_node, tmp_up));
3079 fault = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
3080 index, tmp_up);
3081 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3082 fold_convert (long_integer_type_node, index),
3083 fold_convert (long_integer_type_node, tmp_lo),
3084 fold_convert (long_integer_type_node, tmp_up));
3085 free (msg);
3087 else
3089 tmp_lo = gfc_conv_array_lbound (descriptor, n);
3091 if (name)
3092 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3093 "below lower bound of %%ld", n+1, name);
3094 else
3095 msg = xasprintf ("Index '%%ld' of dimension %d "
3096 "below lower bound of %%ld", n+1);
3098 fault = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3099 index, tmp_lo);
3100 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
3101 fold_convert (long_integer_type_node, index),
3102 fold_convert (long_integer_type_node, tmp_lo));
3103 free (msg);
3106 return index;
3110 /* Return the offset for an index. Performs bound checking for elemental
3111 dimensions. Single element references are processed separately.
3112 DIM is the array dimension, I is the loop dimension. */
3114 static tree
3115 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
3116 gfc_array_ref * ar, tree stride)
3118 gfc_array_info *info;
3119 tree index;
3120 tree desc;
3121 tree data;
3123 info = &ss->info->data.array;
3125 /* Get the index into the array for this dimension. */
3126 if (ar)
3128 gcc_assert (ar->type != AR_ELEMENT);
3129 switch (ar->dimen_type[dim])
3131 case DIMEN_THIS_IMAGE:
3132 gcc_unreachable ();
3133 break;
3134 case DIMEN_ELEMENT:
3135 /* Elemental dimension. */
3136 gcc_assert (info->subscript[dim]
3137 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
3138 /* We've already translated this value outside the loop. */
3139 index = info->subscript[dim]->info->data.scalar.value;
3141 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3142 ar->as->type != AS_ASSUMED_SIZE
3143 || dim < ar->dimen - 1);
3144 break;
3146 case DIMEN_VECTOR:
3147 gcc_assert (info && se->loop);
3148 gcc_assert (info->subscript[dim]
3149 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
3150 desc = info->subscript[dim]->info->data.array.descriptor;
3152 /* Get a zero-based index into the vector. */
3153 index = fold_build2_loc (input_location, MINUS_EXPR,
3154 gfc_array_index_type,
3155 se->loop->loopvar[i], se->loop->from[i]);
3157 /* Multiply the index by the stride. */
3158 index = fold_build2_loc (input_location, MULT_EXPR,
3159 gfc_array_index_type,
3160 index, gfc_conv_array_stride (desc, 0));
3162 /* Read the vector to get an index into info->descriptor. */
3163 data = build_fold_indirect_ref_loc (input_location,
3164 gfc_conv_array_data (desc));
3165 index = gfc_build_array_ref (data, index, NULL);
3166 index = gfc_evaluate_now (index, &se->pre);
3167 index = fold_convert (gfc_array_index_type, index);
3169 /* Do any bounds checking on the final info->descriptor index. */
3170 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
3171 ar->as->type != AS_ASSUMED_SIZE
3172 || dim < ar->dimen - 1);
3173 break;
3175 case DIMEN_RANGE:
3176 /* Scalarized dimension. */
3177 gcc_assert (info && se->loop);
3179 /* Multiply the loop variable by the stride and delta. */
3180 index = se->loop->loopvar[i];
3181 if (!integer_onep (info->stride[dim]))
3182 index = fold_build2_loc (input_location, MULT_EXPR,
3183 gfc_array_index_type, index,
3184 info->stride[dim]);
3185 if (!integer_zerop (info->delta[dim]))
3186 index = fold_build2_loc (input_location, PLUS_EXPR,
3187 gfc_array_index_type, index,
3188 info->delta[dim]);
3189 break;
3191 default:
3192 gcc_unreachable ();
3195 else
3197 /* Temporary array or derived type component. */
3198 gcc_assert (se->loop);
3199 index = se->loop->loopvar[se->loop->order[i]];
3201 /* Pointer functions can have stride[0] different from unity.
3202 Use the stride returned by the function call and stored in
3203 the descriptor for the temporary. */
3204 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
3205 && se->ss->info->expr
3206 && se->ss->info->expr->symtree
3207 && se->ss->info->expr->symtree->n.sym->result
3208 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
3209 stride = gfc_conv_descriptor_stride_get (info->descriptor,
3210 gfc_rank_cst[dim]);
3212 if (info->delta[dim] && !integer_zerop (info->delta[dim]))
3213 index = fold_build2_loc (input_location, PLUS_EXPR,
3214 gfc_array_index_type, index, info->delta[dim]);
3217 /* Multiply by the stride. */
3218 if (stride != NULL && !integer_onep (stride))
3219 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3220 index, stride);
3222 return index;
3226 /* Build a scalarized array reference using the vptr 'size'. */
3228 static bool
3229 build_class_array_ref (gfc_se *se, tree base, tree index)
3231 tree type;
3232 tree size;
3233 tree offset;
3234 tree decl = NULL_TREE;
3235 tree tmp;
3236 gfc_expr *expr = se->ss->info->expr;
3237 gfc_ref *ref;
3238 gfc_ref *class_ref = NULL;
3239 gfc_typespec *ts;
3241 if (se->expr && DECL_P (se->expr) && DECL_LANG_SPECIFIC (se->expr)
3242 && GFC_DECL_SAVED_DESCRIPTOR (se->expr)
3243 && GFC_CLASS_TYPE_P (TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (se->expr))))
3244 decl = se->expr;
3245 else
3247 if (expr == NULL
3248 || (expr->ts.type != BT_CLASS
3249 && !gfc_is_class_array_function (expr)
3250 && !gfc_is_class_array_ref (expr, NULL)))
3251 return false;
3253 if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS)
3254 ts = &expr->symtree->n.sym->ts;
3255 else
3256 ts = NULL;
3258 for (ref = expr->ref; ref; ref = ref->next)
3260 if (ref->type == REF_COMPONENT
3261 && ref->u.c.component->ts.type == BT_CLASS
3262 && ref->next && ref->next->type == REF_COMPONENT
3263 && strcmp (ref->next->u.c.component->name, "_data") == 0
3264 && ref->next->next
3265 && ref->next->next->type == REF_ARRAY
3266 && ref->next->next->u.ar.type != AR_ELEMENT)
3268 ts = &ref->u.c.component->ts;
3269 class_ref = ref;
3270 break;
3274 if (ts == NULL)
3275 return false;
3278 if (class_ref == NULL && expr && expr->symtree->n.sym->attr.function
3279 && expr->symtree->n.sym == expr->symtree->n.sym->result
3280 && expr->symtree->n.sym->backend_decl == current_function_decl)
3282 decl = gfc_get_fake_result_decl (expr->symtree->n.sym, 0);
3284 else if (expr && gfc_is_class_array_function (expr))
3286 size = NULL_TREE;
3287 decl = NULL_TREE;
3288 for (tmp = base; tmp; tmp = TREE_OPERAND (tmp, 0))
3290 tree type;
3291 type = TREE_TYPE (tmp);
3292 while (type)
3294 if (GFC_CLASS_TYPE_P (type))
3295 decl = tmp;
3296 if (type != TYPE_CANONICAL (type))
3297 type = TYPE_CANONICAL (type);
3298 else
3299 type = NULL_TREE;
3301 if (VAR_P (tmp))
3302 break;
3305 if (decl == NULL_TREE)
3306 return false;
3308 se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
3310 else if (class_ref == NULL)
3312 if (decl == NULL_TREE)
3313 decl = expr->symtree->n.sym->backend_decl;
3314 /* For class arrays the tree containing the class is stored in
3315 GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl.
3316 For all others it's sym's backend_decl directly. */
3317 if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
3318 decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
3320 else
3322 /* Remove everything after the last class reference, convert the
3323 expression and then recover its tailend once more. */
3324 gfc_se tmpse;
3325 ref = class_ref->next;
3326 class_ref->next = NULL;
3327 gfc_init_se (&tmpse, NULL);
3328 gfc_conv_expr (&tmpse, expr);
3329 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3330 decl = tmpse.expr;
3331 class_ref->next = ref;
3334 if (POINTER_TYPE_P (TREE_TYPE (decl)))
3335 decl = build_fold_indirect_ref_loc (input_location, decl);
3337 if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
3338 return false;
3340 size = gfc_class_vtab_size_get (decl);
3342 /* For unlimited polymorphic entities then _len component needs to be
3343 multiplied with the size. If no _len component is present, then
3344 gfc_class_len_or_zero_get () return a zero_node. */
3345 tmp = gfc_class_len_or_zero_get (decl);
3346 if (!integer_zerop (tmp))
3347 size = fold_build2 (MULT_EXPR, TREE_TYPE (index),
3348 fold_convert (TREE_TYPE (index), size),
3349 fold_build2 (MAX_EXPR, TREE_TYPE (index),
3350 fold_convert (TREE_TYPE (index), tmp),
3351 fold_convert (TREE_TYPE (index),
3352 integer_one_node)));
3353 else
3354 size = fold_convert (TREE_TYPE (index), size);
3356 /* Build the address of the element. */
3357 type = TREE_TYPE (TREE_TYPE (base));
3358 offset = fold_build2_loc (input_location, MULT_EXPR,
3359 gfc_array_index_type,
3360 index, size);
3361 tmp = gfc_build_addr_expr (pvoid_type_node, base);
3362 tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
3363 tmp = fold_convert (build_pointer_type (type), tmp);
3365 /* Return the element in the se expression. */
3366 se->expr = build_fold_indirect_ref_loc (input_location, tmp);
3367 return true;
3371 /* Build a scalarized reference to an array. */
3373 static void
3374 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
3376 gfc_array_info *info;
3377 tree decl = NULL_TREE;
3378 tree index;
3379 tree base;
3380 gfc_ss *ss;
3381 gfc_expr *expr;
3382 int n;
3384 ss = se->ss;
3385 expr = ss->info->expr;
3386 info = &ss->info->data.array;
3387 if (ar)
3388 n = se->loop->order[0];
3389 else
3390 n = 0;
3392 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
3393 /* Add the offset for this dimension to the stored offset for all other
3394 dimensions. */
3395 if (info->offset && !integer_zerop (info->offset))
3396 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3397 index, info->offset);
3399 base = build_fold_indirect_ref_loc (input_location, info->data);
3401 /* Use the vptr 'size' field to access the element of a class array. */
3402 if (build_class_array_ref (se, base, index))
3403 return;
3405 if (expr && ((is_subref_array (expr)
3406 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor)))
3407 || (expr->ts.deferred && (expr->expr_type == EXPR_VARIABLE
3408 || expr->expr_type == EXPR_FUNCTION))))
3409 decl = expr->symtree->n.sym->backend_decl;
3411 /* A pointer array component can be detected from its field decl. Fix
3412 the descriptor, mark the resulting variable decl and pass it to
3413 gfc_build_array_ref. */
3414 if (is_pointer_array (info->descriptor))
3416 if (TREE_CODE (info->descriptor) == COMPONENT_REF)
3418 decl = gfc_evaluate_now (info->descriptor, &se->pre);
3419 GFC_DECL_PTR_ARRAY_P (decl) = 1;
3420 TREE_USED (decl) = 1;
3422 else if (TREE_CODE (info->descriptor) == INDIRECT_REF)
3423 decl = TREE_OPERAND (info->descriptor, 0);
3425 if (decl == NULL_TREE)
3426 decl = info->descriptor;
3429 se->expr = gfc_build_array_ref (base, index, decl);
3433 /* Translate access of temporary array. */
3435 void
3436 gfc_conv_tmp_array_ref (gfc_se * se)
3438 se->string_length = se->ss->info->string_length;
3439 gfc_conv_scalarized_array_ref (se, NULL);
3440 gfc_advance_se_ss_chain (se);
3443 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3445 static void
3446 add_to_offset (tree *cst_offset, tree *offset, tree t)
3448 if (TREE_CODE (t) == INTEGER_CST)
3449 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3450 else
3452 if (!integer_zerop (*offset))
3453 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3454 gfc_array_index_type, *offset, t);
3455 else
3456 *offset = t;
3461 static tree
3462 build_array_ref (tree desc, tree offset, tree decl, tree vptr)
3464 tree tmp;
3465 tree type;
3466 tree cdesc;
3468 /* For class arrays the class declaration is stored in the saved
3469 descriptor. */
3470 if (INDIRECT_REF_P (desc)
3471 && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
3472 && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
3473 cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
3474 TREE_OPERAND (desc, 0)));
3475 else
3476 cdesc = desc;
3478 /* Class container types do not always have the GFC_CLASS_TYPE_P
3479 but the canonical type does. */
3480 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
3481 && TREE_CODE (cdesc) == COMPONENT_REF)
3483 type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
3484 if (TYPE_CANONICAL (type)
3485 && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
3486 vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
3489 tmp = gfc_conv_array_data (desc);
3490 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3491 tmp = gfc_build_array_ref (tmp, offset, decl, vptr);
3492 return tmp;
3496 /* Build an array reference. se->expr already holds the array descriptor.
3497 This should be either a variable, indirect variable reference or component
3498 reference. For arrays which do not have a descriptor, se->expr will be
3499 the data pointer.
3500 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3502 void
3503 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
3504 locus * where)
3506 int n;
3507 tree offset, cst_offset;
3508 tree tmp;
3509 tree stride;
3510 tree decl = NULL_TREE;
3511 gfc_se indexse;
3512 gfc_se tmpse;
3513 gfc_symbol * sym = expr->symtree->n.sym;
3514 char *var_name = NULL;
3516 if (ar->dimen == 0)
3518 gcc_assert (ar->codimen);
3520 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3521 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
3522 else
3524 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
3525 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
3526 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
3528 /* Use the actual tree type and not the wrapped coarray. */
3529 if (!se->want_pointer)
3530 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
3531 se->expr);
3534 return;
3537 /* Handle scalarized references separately. */
3538 if (ar->type != AR_ELEMENT)
3540 gfc_conv_scalarized_array_ref (se, ar);
3541 gfc_advance_se_ss_chain (se);
3542 return;
3545 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3547 size_t len;
3548 gfc_ref *ref;
3550 len = strlen (sym->name) + 1;
3551 for (ref = expr->ref; ref; ref = ref->next)
3553 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3554 break;
3555 if (ref->type == REF_COMPONENT)
3556 len += 2 + strlen (ref->u.c.component->name);
3559 var_name = XALLOCAVEC (char, len);
3560 strcpy (var_name, sym->name);
3562 for (ref = expr->ref; ref; ref = ref->next)
3564 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3565 break;
3566 if (ref->type == REF_COMPONENT)
3568 strcat (var_name, "%%");
3569 strcat (var_name, ref->u.c.component->name);
3574 cst_offset = offset = gfc_index_zero_node;
3575 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
3577 /* Calculate the offsets from all the dimensions. Make sure to associate
3578 the final offset so that we form a chain of loop invariant summands. */
3579 for (n = ar->dimen - 1; n >= 0; n--)
3581 /* Calculate the index for this dimension. */
3582 gfc_init_se (&indexse, se);
3583 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
3584 gfc_add_block_to_block (&se->pre, &indexse.pre);
3586 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && ! expr->no_bounds_check)
3588 /* Check array bounds. */
3589 tree cond;
3590 char *msg;
3592 /* Evaluate the indexse.expr only once. */
3593 indexse.expr = save_expr (indexse.expr);
3595 /* Lower bound. */
3596 tmp = gfc_conv_array_lbound (se->expr, n);
3597 if (sym->attr.temporary)
3599 gfc_init_se (&tmpse, se);
3600 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
3601 gfc_array_index_type);
3602 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3603 tmp = tmpse.expr;
3606 cond = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
3607 indexse.expr, tmp);
3608 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3609 "below lower bound of %%ld", n+1, var_name);
3610 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3611 fold_convert (long_integer_type_node,
3612 indexse.expr),
3613 fold_convert (long_integer_type_node, tmp));
3614 free (msg);
3616 /* Upper bound, but not for the last dimension of assumed-size
3617 arrays. */
3618 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
3620 tmp = gfc_conv_array_ubound (se->expr, n);
3621 if (sym->attr.temporary)
3623 gfc_init_se (&tmpse, se);
3624 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
3625 gfc_array_index_type);
3626 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3627 tmp = tmpse.expr;
3630 cond = fold_build2_loc (input_location, GT_EXPR,
3631 logical_type_node, indexse.expr, tmp);
3632 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3633 "above upper bound of %%ld", n+1, var_name);
3634 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3635 fold_convert (long_integer_type_node,
3636 indexse.expr),
3637 fold_convert (long_integer_type_node, tmp));
3638 free (msg);
3642 /* Multiply the index by the stride. */
3643 stride = gfc_conv_array_stride (se->expr, n);
3644 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3645 indexse.expr, stride);
3647 /* And add it to the total. */
3648 add_to_offset (&cst_offset, &offset, tmp);
3651 if (!integer_zerop (cst_offset))
3652 offset = fold_build2_loc (input_location, PLUS_EXPR,
3653 gfc_array_index_type, offset, cst_offset);
3655 /* A pointer array component can be detected from its field decl. Fix
3656 the descriptor, mark the resulting variable decl and pass it to
3657 build_array_ref. */
3658 if (!expr->ts.deferred && !sym->attr.codimension
3659 && is_pointer_array (se->expr))
3661 if (TREE_CODE (se->expr) == COMPONENT_REF)
3663 decl = gfc_evaluate_now (se->expr, &se->pre);
3664 GFC_DECL_PTR_ARRAY_P (decl) = 1;
3665 TREE_USED (decl) = 1;
3667 else if (TREE_CODE (se->expr) == INDIRECT_REF)
3668 decl = TREE_OPERAND (se->expr, 0);
3669 else
3670 decl = se->expr;
3672 else if (expr->ts.deferred
3673 || (sym->ts.type == BT_CHARACTER
3674 && sym->attr.select_type_temporary))
3675 decl = sym->backend_decl;
3676 else if (sym->ts.type == BT_CLASS)
3677 decl = NULL_TREE;
3679 se->expr = build_array_ref (se->expr, offset, decl, se->class_vptr);
3683 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
3684 LOOP_DIM dimension (if any) to array's offset. */
3686 static void
3687 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
3688 gfc_array_ref *ar, int array_dim, int loop_dim)
3690 gfc_se se;
3691 gfc_array_info *info;
3692 tree stride, index;
3694 info = &ss->info->data.array;
3696 gfc_init_se (&se, NULL);
3697 se.loop = loop;
3698 se.expr = info->descriptor;
3699 stride = gfc_conv_array_stride (info->descriptor, array_dim);
3700 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
3701 gfc_add_block_to_block (pblock, &se.pre);
3703 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
3704 gfc_array_index_type,
3705 info->offset, index);
3706 info->offset = gfc_evaluate_now (info->offset, pblock);
3710 /* Generate the code to be executed immediately before entering a
3711 scalarization loop. */
3713 static void
3714 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
3715 stmtblock_t * pblock)
3717 tree stride;
3718 gfc_ss_info *ss_info;
3719 gfc_array_info *info;
3720 gfc_ss_type ss_type;
3721 gfc_ss *ss, *pss;
3722 gfc_loopinfo *ploop;
3723 gfc_array_ref *ar;
3724 int i;
3726 /* This code will be executed before entering the scalarization loop
3727 for this dimension. */
3728 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3730 ss_info = ss->info;
3732 if ((ss_info->useflags & flag) == 0)
3733 continue;
3735 ss_type = ss_info->type;
3736 if (ss_type != GFC_SS_SECTION
3737 && ss_type != GFC_SS_FUNCTION
3738 && ss_type != GFC_SS_CONSTRUCTOR
3739 && ss_type != GFC_SS_COMPONENT)
3740 continue;
3742 info = &ss_info->data.array;
3744 gcc_assert (dim < ss->dimen);
3745 gcc_assert (ss->dimen == loop->dimen);
3747 if (info->ref)
3748 ar = &info->ref->u.ar;
3749 else
3750 ar = NULL;
3752 if (dim == loop->dimen - 1 && loop->parent != NULL)
3754 /* If we are in the outermost dimension of this loop, the previous
3755 dimension shall be in the parent loop. */
3756 gcc_assert (ss->parent != NULL);
3758 pss = ss->parent;
3759 ploop = loop->parent;
3761 /* ss and ss->parent are about the same array. */
3762 gcc_assert (ss_info == pss->info);
3764 else
3766 ploop = loop;
3767 pss = ss;
3770 if (dim == loop->dimen - 1)
3771 i = 0;
3772 else
3773 i = dim + 1;
3775 /* For the time being, there is no loop reordering. */
3776 gcc_assert (i == ploop->order[i]);
3777 i = ploop->order[i];
3779 if (dim == loop->dimen - 1 && loop->parent == NULL)
3781 stride = gfc_conv_array_stride (info->descriptor,
3782 innermost_ss (ss)->dim[i]);
3784 /* Calculate the stride of the innermost loop. Hopefully this will
3785 allow the backend optimizers to do their stuff more effectively.
3787 info->stride0 = gfc_evaluate_now (stride, pblock);
3789 /* For the outermost loop calculate the offset due to any
3790 elemental dimensions. It will have been initialized with the
3791 base offset of the array. */
3792 if (info->ref)
3794 for (i = 0; i < ar->dimen; i++)
3796 if (ar->dimen_type[i] != DIMEN_ELEMENT)
3797 continue;
3799 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
3803 else
3804 /* Add the offset for the previous loop dimension. */
3805 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
3807 /* Remember this offset for the second loop. */
3808 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
3809 info->saved_offset = info->offset;
3814 /* Start a scalarized expression. Creates a scope and declares loop
3815 variables. */
3817 void
3818 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
3820 int dim;
3821 int n;
3822 int flags;
3824 gcc_assert (!loop->array_parameter);
3826 for (dim = loop->dimen - 1; dim >= 0; dim--)
3828 n = loop->order[dim];
3830 gfc_start_block (&loop->code[n]);
3832 /* Create the loop variable. */
3833 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
3835 if (dim < loop->temp_dim)
3836 flags = 3;
3837 else
3838 flags = 1;
3839 /* Calculate values that will be constant within this loop. */
3840 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3842 gfc_start_block (pbody);
3846 /* Generates the actual loop code for a scalarization loop. */
3848 void
3849 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3850 stmtblock_t * pbody)
3852 stmtblock_t block;
3853 tree cond;
3854 tree tmp;
3855 tree loopbody;
3856 tree exit_label;
3857 tree stmt;
3858 tree init;
3859 tree incr;
3861 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS
3862 | OMPWS_SCALARIZER_BODY))
3863 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3864 && n == loop->dimen - 1)
3866 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3867 init = make_tree_vec (1);
3868 cond = make_tree_vec (1);
3869 incr = make_tree_vec (1);
3871 /* Cycle statement is implemented with a goto. Exit statement must not
3872 be present for this loop. */
3873 exit_label = gfc_build_label_decl (NULL_TREE);
3874 TREE_USED (exit_label) = 1;
3876 /* Label for cycle statements (if needed). */
3877 tmp = build1_v (LABEL_EXPR, exit_label);
3878 gfc_add_expr_to_block (pbody, tmp);
3880 stmt = make_node (OMP_FOR);
3882 TREE_TYPE (stmt) = void_type_node;
3883 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3885 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3886 OMP_CLAUSE_SCHEDULE);
3887 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3888 = OMP_CLAUSE_SCHEDULE_STATIC;
3889 if (ompws_flags & OMPWS_NOWAIT)
3890 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3891 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3893 /* Initialize the loopvar. */
3894 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3895 loop->from[n]);
3896 OMP_FOR_INIT (stmt) = init;
3897 /* The exit condition. */
3898 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3899 logical_type_node,
3900 loop->loopvar[n], loop->to[n]);
3901 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3902 OMP_FOR_COND (stmt) = cond;
3903 /* Increment the loopvar. */
3904 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3905 loop->loopvar[n], gfc_index_one_node);
3906 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3907 void_type_node, loop->loopvar[n], tmp);
3908 OMP_FOR_INCR (stmt) = incr;
3910 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3911 gfc_add_expr_to_block (&loop->code[n], stmt);
3913 else
3915 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3916 && (loop->temp_ss == NULL);
3918 loopbody = gfc_finish_block (pbody);
3920 if (reverse_loop)
3921 std::swap (loop->from[n], loop->to[n]);
3923 /* Initialize the loopvar. */
3924 if (loop->loopvar[n] != loop->from[n])
3925 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3927 exit_label = gfc_build_label_decl (NULL_TREE);
3929 /* Generate the loop body. */
3930 gfc_init_block (&block);
3932 /* The exit condition. */
3933 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3934 logical_type_node, loop->loopvar[n], loop->to[n]);
3935 tmp = build1_v (GOTO_EXPR, exit_label);
3936 TREE_USED (exit_label) = 1;
3937 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3938 gfc_add_expr_to_block (&block, tmp);
3940 /* The main body. */
3941 gfc_add_expr_to_block (&block, loopbody);
3943 /* Increment the loopvar. */
3944 tmp = fold_build2_loc (input_location,
3945 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3946 gfc_array_index_type, loop->loopvar[n],
3947 gfc_index_one_node);
3949 gfc_add_modify (&block, loop->loopvar[n], tmp);
3951 /* Build the loop. */
3952 tmp = gfc_finish_block (&block);
3953 tmp = build1_v (LOOP_EXPR, tmp);
3954 gfc_add_expr_to_block (&loop->code[n], tmp);
3956 /* Add the exit label. */
3957 tmp = build1_v (LABEL_EXPR, exit_label);
3958 gfc_add_expr_to_block (&loop->code[n], tmp);
3964 /* Finishes and generates the loops for a scalarized expression. */
3966 void
3967 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3969 int dim;
3970 int n;
3971 gfc_ss *ss;
3972 stmtblock_t *pblock;
3973 tree tmp;
3975 pblock = body;
3976 /* Generate the loops. */
3977 for (dim = 0; dim < loop->dimen; dim++)
3979 n = loop->order[dim];
3980 gfc_trans_scalarized_loop_end (loop, n, pblock);
3981 loop->loopvar[n] = NULL_TREE;
3982 pblock = &loop->code[n];
3985 tmp = gfc_finish_block (pblock);
3986 gfc_add_expr_to_block (&loop->pre, tmp);
3988 /* Clear all the used flags. */
3989 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3990 if (ss->parent == NULL)
3991 ss->info->useflags = 0;
3995 /* Finish the main body of a scalarized expression, and start the secondary
3996 copying body. */
3998 void
3999 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
4001 int dim;
4002 int n;
4003 stmtblock_t *pblock;
4004 gfc_ss *ss;
4006 pblock = body;
4007 /* We finish as many loops as are used by the temporary. */
4008 for (dim = 0; dim < loop->temp_dim - 1; dim++)
4010 n = loop->order[dim];
4011 gfc_trans_scalarized_loop_end (loop, n, pblock);
4012 loop->loopvar[n] = NULL_TREE;
4013 pblock = &loop->code[n];
4016 /* We don't want to finish the outermost loop entirely. */
4017 n = loop->order[loop->temp_dim - 1];
4018 gfc_trans_scalarized_loop_end (loop, n, pblock);
4020 /* Restore the initial offsets. */
4021 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4023 gfc_ss_type ss_type;
4024 gfc_ss_info *ss_info;
4026 ss_info = ss->info;
4028 if ((ss_info->useflags & 2) == 0)
4029 continue;
4031 ss_type = ss_info->type;
4032 if (ss_type != GFC_SS_SECTION
4033 && ss_type != GFC_SS_FUNCTION
4034 && ss_type != GFC_SS_CONSTRUCTOR
4035 && ss_type != GFC_SS_COMPONENT)
4036 continue;
4038 ss_info->data.array.offset = ss_info->data.array.saved_offset;
4041 /* Restart all the inner loops we just finished. */
4042 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
4044 n = loop->order[dim];
4046 gfc_start_block (&loop->code[n]);
4048 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
4050 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
4053 /* Start a block for the secondary copying code. */
4054 gfc_start_block (body);
4058 /* Precalculate (either lower or upper) bound of an array section.
4059 BLOCK: Block in which the (pre)calculation code will go.
4060 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
4061 VALUES[DIM]: Specified bound (NULL <=> unspecified).
4062 DESC: Array descriptor from which the bound will be picked if unspecified
4063 (either lower or upper bound according to LBOUND). */
4065 static void
4066 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
4067 tree desc, int dim, bool lbound, bool deferred)
4069 gfc_se se;
4070 gfc_expr * input_val = values[dim];
4071 tree *output = &bounds[dim];
4074 if (input_val)
4076 /* Specified section bound. */
4077 gfc_init_se (&se, NULL);
4078 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
4079 gfc_add_block_to_block (block, &se.pre);
4080 *output = se.expr;
4082 else if (deferred && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
4084 /* The gfc_conv_array_lbound () routine returns a constant zero for
4085 deferred length arrays, which in the scalarizer wreaks havoc, when
4086 copying to a (newly allocated) one-based array.
4087 Keep returning the actual result in sync for both bounds. */
4088 *output = lbound ? gfc_conv_descriptor_lbound_get (desc,
4089 gfc_rank_cst[dim]):
4090 gfc_conv_descriptor_ubound_get (desc,
4091 gfc_rank_cst[dim]);
4093 else
4095 /* No specific bound specified so use the bound of the array. */
4096 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
4097 gfc_conv_array_ubound (desc, dim);
4099 *output = gfc_evaluate_now (*output, block);
4103 /* Calculate the lower bound of an array section. */
4105 static void
4106 gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
4108 gfc_expr *stride = NULL;
4109 tree desc;
4110 gfc_se se;
4111 gfc_array_info *info;
4112 gfc_array_ref *ar;
4114 gcc_assert (ss->info->type == GFC_SS_SECTION);
4116 info = &ss->info->data.array;
4117 ar = &info->ref->u.ar;
4119 if (ar->dimen_type[dim] == DIMEN_VECTOR)
4121 /* We use a zero-based index to access the vector. */
4122 info->start[dim] = gfc_index_zero_node;
4123 info->end[dim] = NULL;
4124 info->stride[dim] = gfc_index_one_node;
4125 return;
4128 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
4129 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
4130 desc = info->descriptor;
4131 stride = ar->stride[dim];
4134 /* Calculate the start of the range. For vector subscripts this will
4135 be the range of the vector. */
4136 evaluate_bound (block, info->start, ar->start, desc, dim, true,
4137 ar->as->type == AS_DEFERRED);
4139 /* Similarly calculate the end. Although this is not used in the
4140 scalarizer, it is needed when checking bounds and where the end
4141 is an expression with side-effects. */
4142 evaluate_bound (block, info->end, ar->end, desc, dim, false,
4143 ar->as->type == AS_DEFERRED);
4146 /* Calculate the stride. */
4147 if (stride == NULL)
4148 info->stride[dim] = gfc_index_one_node;
4149 else
4151 gfc_init_se (&se, NULL);
4152 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
4153 gfc_add_block_to_block (block, &se.pre);
4154 info->stride[dim] = gfc_evaluate_now (se.expr, block);
4159 /* Calculates the range start and stride for a SS chain. Also gets the
4160 descriptor and data pointer. The range of vector subscripts is the size
4161 of the vector. Array bounds are also checked. */
4163 void
4164 gfc_conv_ss_startstride (gfc_loopinfo * loop)
4166 int n;
4167 tree tmp;
4168 gfc_ss *ss;
4169 tree desc;
4171 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4173 loop->dimen = 0;
4174 /* Determine the rank of the loop. */
4175 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4177 switch (ss->info->type)
4179 case GFC_SS_SECTION:
4180 case GFC_SS_CONSTRUCTOR:
4181 case GFC_SS_FUNCTION:
4182 case GFC_SS_COMPONENT:
4183 loop->dimen = ss->dimen;
4184 goto done;
4186 /* As usual, lbound and ubound are exceptions!. */
4187 case GFC_SS_INTRINSIC:
4188 switch (ss->info->expr->value.function.isym->id)
4190 case GFC_ISYM_LBOUND:
4191 case GFC_ISYM_UBOUND:
4192 case GFC_ISYM_LCOBOUND:
4193 case GFC_ISYM_UCOBOUND:
4194 case GFC_ISYM_THIS_IMAGE:
4195 loop->dimen = ss->dimen;
4196 goto done;
4198 default:
4199 break;
4202 default:
4203 break;
4207 /* We should have determined the rank of the expression by now. If
4208 not, that's bad news. */
4209 gcc_unreachable ();
4211 done:
4212 /* Loop over all the SS in the chain. */
4213 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4215 gfc_ss_info *ss_info;
4216 gfc_array_info *info;
4217 gfc_expr *expr;
4219 ss_info = ss->info;
4220 expr = ss_info->expr;
4221 info = &ss_info->data.array;
4223 if (expr && expr->shape && !info->shape)
4224 info->shape = expr->shape;
4226 switch (ss_info->type)
4228 case GFC_SS_SECTION:
4229 /* Get the descriptor for the array. If it is a cross loops array,
4230 we got the descriptor already in the outermost loop. */
4231 if (ss->parent == NULL)
4232 gfc_conv_ss_descriptor (&outer_loop->pre, ss,
4233 !loop->array_parameter);
4235 for (n = 0; n < ss->dimen; n++)
4236 gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
4237 break;
4239 case GFC_SS_INTRINSIC:
4240 switch (expr->value.function.isym->id)
4242 /* Fall through to supply start and stride. */
4243 case GFC_ISYM_LBOUND:
4244 case GFC_ISYM_UBOUND:
4246 gfc_expr *arg;
4248 /* This is the variant without DIM=... */
4249 gcc_assert (expr->value.function.actual->next->expr == NULL);
4251 arg = expr->value.function.actual->expr;
4252 if (arg->rank == -1)
4254 gfc_se se;
4255 tree rank, tmp;
4257 /* The rank (hence the return value's shape) is unknown,
4258 we have to retrieve it. */
4259 gfc_init_se (&se, NULL);
4260 se.descriptor_only = 1;
4261 gfc_conv_expr (&se, arg);
4262 /* This is a bare variable, so there is no preliminary
4263 or cleanup code. */
4264 gcc_assert (se.pre.head == NULL_TREE
4265 && se.post.head == NULL_TREE);
4266 rank = gfc_conv_descriptor_rank (se.expr);
4267 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4268 gfc_array_index_type,
4269 fold_convert (gfc_array_index_type,
4270 rank),
4271 gfc_index_one_node);
4272 info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
4273 info->start[0] = gfc_index_zero_node;
4274 info->stride[0] = gfc_index_one_node;
4275 continue;
4277 /* Otherwise fall through GFC_SS_FUNCTION. */
4278 gcc_fallthrough ();
4280 case GFC_ISYM_LCOBOUND:
4281 case GFC_ISYM_UCOBOUND:
4282 case GFC_ISYM_THIS_IMAGE:
4283 break;
4285 default:
4286 continue;
4289 /* FALLTHRU */
4290 case GFC_SS_CONSTRUCTOR:
4291 case GFC_SS_FUNCTION:
4292 for (n = 0; n < ss->dimen; n++)
4294 int dim = ss->dim[n];
4296 info->start[dim] = gfc_index_zero_node;
4297 info->end[dim] = gfc_index_zero_node;
4298 info->stride[dim] = gfc_index_one_node;
4300 break;
4302 default:
4303 break;
4307 /* The rest is just runtime bounds checking. */
4308 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4310 stmtblock_t block;
4311 tree lbound, ubound;
4312 tree end;
4313 tree size[GFC_MAX_DIMENSIONS];
4314 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
4315 gfc_array_info *info;
4316 char *msg;
4317 int dim;
4319 gfc_start_block (&block);
4321 for (n = 0; n < loop->dimen; n++)
4322 size[n] = NULL_TREE;
4324 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4326 stmtblock_t inner;
4327 gfc_ss_info *ss_info;
4328 gfc_expr *expr;
4329 locus *expr_loc;
4330 const char *expr_name;
4332 ss_info = ss->info;
4333 if (ss_info->type != GFC_SS_SECTION)
4334 continue;
4336 /* Catch allocatable lhs in f2003. */
4337 if (flag_realloc_lhs && ss->no_bounds_check)
4338 continue;
4340 expr = ss_info->expr;
4341 expr_loc = &expr->where;
4342 expr_name = expr->symtree->name;
4344 gfc_start_block (&inner);
4346 /* TODO: range checking for mapped dimensions. */
4347 info = &ss_info->data.array;
4349 /* This code only checks ranges. Elemental and vector
4350 dimensions are checked later. */
4351 for (n = 0; n < loop->dimen; n++)
4353 bool check_upper;
4355 dim = ss->dim[n];
4356 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
4357 continue;
4359 if (dim == info->ref->u.ar.dimen - 1
4360 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
4361 check_upper = false;
4362 else
4363 check_upper = true;
4365 /* Zero stride is not allowed. */
4366 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
4367 info->stride[dim], gfc_index_zero_node);
4368 msg = xasprintf ("Zero stride is not allowed, for dimension %d "
4369 "of array '%s'", dim + 1, expr_name);
4370 gfc_trans_runtime_check (true, false, tmp, &inner,
4371 expr_loc, msg);
4372 free (msg);
4374 desc = info->descriptor;
4376 /* This is the run-time equivalent of resolve.c's
4377 check_dimension(). The logical is more readable there
4378 than it is here, with all the trees. */
4379 lbound = gfc_conv_array_lbound (desc, dim);
4380 end = info->end[dim];
4381 if (check_upper)
4382 ubound = gfc_conv_array_ubound (desc, dim);
4383 else
4384 ubound = NULL;
4386 /* non_zerosized is true when the selected range is not
4387 empty. */
4388 stride_pos = fold_build2_loc (input_location, GT_EXPR,
4389 logical_type_node, info->stride[dim],
4390 gfc_index_zero_node);
4391 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4392 info->start[dim], end);
4393 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4394 logical_type_node, stride_pos, tmp);
4396 stride_neg = fold_build2_loc (input_location, LT_EXPR,
4397 logical_type_node,
4398 info->stride[dim], gfc_index_zero_node);
4399 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
4400 info->start[dim], end);
4401 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4402 logical_type_node,
4403 stride_neg, tmp);
4404 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4405 logical_type_node,
4406 stride_pos, stride_neg);
4408 /* Check the start of the range against the lower and upper
4409 bounds of the array, if the range is not empty.
4410 If upper bound is present, include both bounds in the
4411 error message. */
4412 if (check_upper)
4414 tmp = fold_build2_loc (input_location, LT_EXPR,
4415 logical_type_node,
4416 info->start[dim], lbound);
4417 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4418 logical_type_node,
4419 non_zerosized, tmp);
4420 tmp2 = fold_build2_loc (input_location, GT_EXPR,
4421 logical_type_node,
4422 info->start[dim], ubound);
4423 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4424 logical_type_node,
4425 non_zerosized, tmp2);
4426 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4427 "outside of expected range (%%ld:%%ld)",
4428 dim + 1, expr_name);
4429 gfc_trans_runtime_check (true, false, tmp, &inner,
4430 expr_loc, msg,
4431 fold_convert (long_integer_type_node, info->start[dim]),
4432 fold_convert (long_integer_type_node, lbound),
4433 fold_convert (long_integer_type_node, ubound));
4434 gfc_trans_runtime_check (true, false, tmp2, &inner,
4435 expr_loc, msg,
4436 fold_convert (long_integer_type_node, info->start[dim]),
4437 fold_convert (long_integer_type_node, lbound),
4438 fold_convert (long_integer_type_node, ubound));
4439 free (msg);
4441 else
4443 tmp = fold_build2_loc (input_location, LT_EXPR,
4444 logical_type_node,
4445 info->start[dim], lbound);
4446 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4447 logical_type_node, non_zerosized, tmp);
4448 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4449 "below lower bound of %%ld",
4450 dim + 1, expr_name);
4451 gfc_trans_runtime_check (true, false, tmp, &inner,
4452 expr_loc, msg,
4453 fold_convert (long_integer_type_node, info->start[dim]),
4454 fold_convert (long_integer_type_node, lbound));
4455 free (msg);
4458 /* Compute the last element of the range, which is not
4459 necessarily "end" (think 0:5:3, which doesn't contain 5)
4460 and check it against both lower and upper bounds. */
4462 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4463 gfc_array_index_type, end,
4464 info->start[dim]);
4465 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
4466 gfc_array_index_type, tmp,
4467 info->stride[dim]);
4468 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4469 gfc_array_index_type, end, tmp);
4470 tmp2 = fold_build2_loc (input_location, LT_EXPR,
4471 logical_type_node, tmp, lbound);
4472 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4473 logical_type_node, non_zerosized, tmp2);
4474 if (check_upper)
4476 tmp3 = fold_build2_loc (input_location, GT_EXPR,
4477 logical_type_node, tmp, ubound);
4478 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4479 logical_type_node, non_zerosized, tmp3);
4480 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4481 "outside of expected range (%%ld:%%ld)",
4482 dim + 1, expr_name);
4483 gfc_trans_runtime_check (true, false, tmp2, &inner,
4484 expr_loc, msg,
4485 fold_convert (long_integer_type_node, tmp),
4486 fold_convert (long_integer_type_node, ubound),
4487 fold_convert (long_integer_type_node, lbound));
4488 gfc_trans_runtime_check (true, false, tmp3, &inner,
4489 expr_loc, msg,
4490 fold_convert (long_integer_type_node, tmp),
4491 fold_convert (long_integer_type_node, ubound),
4492 fold_convert (long_integer_type_node, lbound));
4493 free (msg);
4495 else
4497 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4498 "below lower bound of %%ld",
4499 dim + 1, expr_name);
4500 gfc_trans_runtime_check (true, false, tmp2, &inner,
4501 expr_loc, msg,
4502 fold_convert (long_integer_type_node, tmp),
4503 fold_convert (long_integer_type_node, lbound));
4504 free (msg);
4507 /* Check the section sizes match. */
4508 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4509 gfc_array_index_type, end,
4510 info->start[dim]);
4511 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4512 gfc_array_index_type, tmp,
4513 info->stride[dim]);
4514 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4515 gfc_array_index_type,
4516 gfc_index_one_node, tmp);
4517 tmp = fold_build2_loc (input_location, MAX_EXPR,
4518 gfc_array_index_type, tmp,
4519 build_int_cst (gfc_array_index_type, 0));
4520 /* We remember the size of the first section, and check all the
4521 others against this. */
4522 if (size[n])
4524 tmp3 = fold_build2_loc (input_location, NE_EXPR,
4525 logical_type_node, tmp, size[n]);
4526 msg = xasprintf ("Array bound mismatch for dimension %d "
4527 "of array '%s' (%%ld/%%ld)",
4528 dim + 1, expr_name);
4530 gfc_trans_runtime_check (true, false, tmp3, &inner,
4531 expr_loc, msg,
4532 fold_convert (long_integer_type_node, tmp),
4533 fold_convert (long_integer_type_node, size[n]));
4535 free (msg);
4537 else
4538 size[n] = gfc_evaluate_now (tmp, &inner);
4541 tmp = gfc_finish_block (&inner);
4543 /* For optional arguments, only check bounds if the argument is
4544 present. */
4545 if (expr->symtree->n.sym->attr.optional
4546 || expr->symtree->n.sym->attr.not_always_present)
4547 tmp = build3_v (COND_EXPR,
4548 gfc_conv_expr_present (expr->symtree->n.sym),
4549 tmp, build_empty_stmt (input_location));
4551 gfc_add_expr_to_block (&block, tmp);
4555 tmp = gfc_finish_block (&block);
4556 gfc_add_expr_to_block (&outer_loop->pre, tmp);
4559 for (loop = loop->nested; loop; loop = loop->next)
4560 gfc_conv_ss_startstride (loop);
4563 /* Return true if both symbols could refer to the same data object. Does
4564 not take account of aliasing due to equivalence statements. */
4566 static int
4567 symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
4568 bool lsym_target, bool rsym_pointer, bool rsym_target)
4570 /* Aliasing isn't possible if the symbols have different base types. */
4571 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
4572 return 0;
4574 /* Pointers can point to other pointers and target objects. */
4576 if ((lsym_pointer && (rsym_pointer || rsym_target))
4577 || (rsym_pointer && (lsym_pointer || lsym_target)))
4578 return 1;
4580 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
4581 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
4582 checked above. */
4583 if (lsym_target && rsym_target
4584 && ((lsym->attr.dummy && !lsym->attr.contiguous
4585 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
4586 || (rsym->attr.dummy && !rsym->attr.contiguous
4587 && (!rsym->attr.dimension
4588 || rsym->as->type == AS_ASSUMED_SHAPE))))
4589 return 1;
4591 return 0;
4595 /* Return true if the two SS could be aliased, i.e. both point to the same data
4596 object. */
4597 /* TODO: resolve aliases based on frontend expressions. */
4599 static int
4600 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
4602 gfc_ref *lref;
4603 gfc_ref *rref;
4604 gfc_expr *lexpr, *rexpr;
4605 gfc_symbol *lsym;
4606 gfc_symbol *rsym;
4607 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
4609 lexpr = lss->info->expr;
4610 rexpr = rss->info->expr;
4612 lsym = lexpr->symtree->n.sym;
4613 rsym = rexpr->symtree->n.sym;
4615 lsym_pointer = lsym->attr.pointer;
4616 lsym_target = lsym->attr.target;
4617 rsym_pointer = rsym->attr.pointer;
4618 rsym_target = rsym->attr.target;
4620 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
4621 rsym_pointer, rsym_target))
4622 return 1;
4624 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
4625 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
4626 return 0;
4628 /* For derived types we must check all the component types. We can ignore
4629 array references as these will have the same base type as the previous
4630 component ref. */
4631 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
4633 if (lref->type != REF_COMPONENT)
4634 continue;
4636 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
4637 lsym_target = lsym_target || lref->u.c.sym->attr.target;
4639 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
4640 rsym_pointer, rsym_target))
4641 return 1;
4643 if ((lsym_pointer && (rsym_pointer || rsym_target))
4644 || (rsym_pointer && (lsym_pointer || lsym_target)))
4646 if (gfc_compare_types (&lref->u.c.component->ts,
4647 &rsym->ts))
4648 return 1;
4651 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
4652 rref = rref->next)
4654 if (rref->type != REF_COMPONENT)
4655 continue;
4657 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4658 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4660 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
4661 lsym_pointer, lsym_target,
4662 rsym_pointer, rsym_target))
4663 return 1;
4665 if ((lsym_pointer && (rsym_pointer || rsym_target))
4666 || (rsym_pointer && (lsym_pointer || lsym_target)))
4668 if (gfc_compare_types (&lref->u.c.component->ts,
4669 &rref->u.c.sym->ts))
4670 return 1;
4671 if (gfc_compare_types (&lref->u.c.sym->ts,
4672 &rref->u.c.component->ts))
4673 return 1;
4674 if (gfc_compare_types (&lref->u.c.component->ts,
4675 &rref->u.c.component->ts))
4676 return 1;
4681 lsym_pointer = lsym->attr.pointer;
4682 lsym_target = lsym->attr.target;
4683 lsym_pointer = lsym->attr.pointer;
4684 lsym_target = lsym->attr.target;
4686 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
4688 if (rref->type != REF_COMPONENT)
4689 break;
4691 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4692 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4694 if (symbols_could_alias (rref->u.c.sym, lsym,
4695 lsym_pointer, lsym_target,
4696 rsym_pointer, rsym_target))
4697 return 1;
4699 if ((lsym_pointer && (rsym_pointer || rsym_target))
4700 || (rsym_pointer && (lsym_pointer || lsym_target)))
4702 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
4703 return 1;
4707 return 0;
4711 /* Resolve array data dependencies. Creates a temporary if required. */
4712 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
4713 dependency.c. */
4715 void
4716 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
4717 gfc_ss * rss)
4719 gfc_ss *ss;
4720 gfc_ref *lref;
4721 gfc_ref *rref;
4722 gfc_ss_info *ss_info;
4723 gfc_expr *dest_expr;
4724 gfc_expr *ss_expr;
4725 int nDepend = 0;
4726 int i, j;
4728 loop->temp_ss = NULL;
4729 dest_expr = dest->info->expr;
4731 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
4733 ss_info = ss->info;
4734 ss_expr = ss_info->expr;
4736 if (ss_info->array_outer_dependency)
4738 nDepend = 1;
4739 break;
4742 if (ss_info->type != GFC_SS_SECTION)
4744 if (flag_realloc_lhs
4745 && dest_expr != ss_expr
4746 && gfc_is_reallocatable_lhs (dest_expr)
4747 && ss_expr->rank)
4748 nDepend = gfc_check_dependency (dest_expr, ss_expr, true);
4750 /* Check for cases like c(:)(1:2) = c(2)(2:3) */
4751 if (!nDepend && dest_expr->rank > 0
4752 && dest_expr->ts.type == BT_CHARACTER
4753 && ss_expr->expr_type == EXPR_VARIABLE)
4755 nDepend = gfc_check_dependency (dest_expr, ss_expr, false);
4757 if (ss_info->type == GFC_SS_REFERENCE
4758 && gfc_check_dependency (dest_expr, ss_expr, false))
4759 ss_info->data.scalar.needs_temporary = 1;
4761 if (nDepend)
4762 break;
4763 else
4764 continue;
4767 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
4769 if (gfc_could_be_alias (dest, ss)
4770 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
4772 nDepend = 1;
4773 break;
4776 else
4778 lref = dest_expr->ref;
4779 rref = ss_expr->ref;
4781 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
4783 if (nDepend == 1)
4784 break;
4786 for (i = 0; i < dest->dimen; i++)
4787 for (j = 0; j < ss->dimen; j++)
4788 if (i != j
4789 && dest->dim[i] == ss->dim[j])
4791 /* If we don't access array elements in the same order,
4792 there is a dependency. */
4793 nDepend = 1;
4794 goto temporary;
4796 #if 0
4797 /* TODO : loop shifting. */
4798 if (nDepend == 1)
4800 /* Mark the dimensions for LOOP SHIFTING */
4801 for (n = 0; n < loop->dimen; n++)
4803 int dim = dest->data.info.dim[n];
4805 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
4806 depends[n] = 2;
4807 else if (! gfc_is_same_range (&lref->u.ar,
4808 &rref->u.ar, dim, 0))
4809 depends[n] = 1;
4812 /* Put all the dimensions with dependencies in the
4813 innermost loops. */
4814 dim = 0;
4815 for (n = 0; n < loop->dimen; n++)
4817 gcc_assert (loop->order[n] == n);
4818 if (depends[n])
4819 loop->order[dim++] = n;
4821 for (n = 0; n < loop->dimen; n++)
4823 if (! depends[n])
4824 loop->order[dim++] = n;
4827 gcc_assert (dim == loop->dimen);
4828 break;
4830 #endif
4834 temporary:
4836 if (nDepend == 1)
4838 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
4839 if (GFC_ARRAY_TYPE_P (base_type)
4840 || GFC_DESCRIPTOR_TYPE_P (base_type))
4841 base_type = gfc_get_element_type (base_type);
4842 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
4843 loop->dimen);
4844 gfc_add_ss_to_loop (loop, loop->temp_ss);
4846 else
4847 loop->temp_ss = NULL;
4851 /* Browse through each array's information from the scalarizer and set the loop
4852 bounds according to the "best" one (per dimension), i.e. the one which
4853 provides the most information (constant bounds, shape, etc.). */
4855 static void
4856 set_loop_bounds (gfc_loopinfo *loop)
4858 int n, dim, spec_dim;
4859 gfc_array_info *info;
4860 gfc_array_info *specinfo;
4861 gfc_ss *ss;
4862 tree tmp;
4863 gfc_ss **loopspec;
4864 bool dynamic[GFC_MAX_DIMENSIONS];
4865 mpz_t *cshape;
4866 mpz_t i;
4867 bool nonoptional_arr;
4869 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4871 loopspec = loop->specloop;
4873 mpz_init (i);
4874 for (n = 0; n < loop->dimen; n++)
4876 loopspec[n] = NULL;
4877 dynamic[n] = false;
4879 /* If there are both optional and nonoptional array arguments, scalarize
4880 over the nonoptional; otherwise, it does not matter as then all
4881 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
4883 nonoptional_arr = false;
4885 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4886 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
4887 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
4889 nonoptional_arr = true;
4890 break;
4893 /* We use one SS term, and use that to determine the bounds of the
4894 loop for this dimension. We try to pick the simplest term. */
4895 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4897 gfc_ss_type ss_type;
4899 ss_type = ss->info->type;
4900 if (ss_type == GFC_SS_SCALAR
4901 || ss_type == GFC_SS_TEMP
4902 || ss_type == GFC_SS_REFERENCE
4903 || (ss->info->can_be_null_ref && nonoptional_arr))
4904 continue;
4906 info = &ss->info->data.array;
4907 dim = ss->dim[n];
4909 if (loopspec[n] != NULL)
4911 specinfo = &loopspec[n]->info->data.array;
4912 spec_dim = loopspec[n]->dim[n];
4914 else
4916 /* Silence uninitialized warnings. */
4917 specinfo = NULL;
4918 spec_dim = 0;
4921 if (info->shape)
4923 gcc_assert (info->shape[dim]);
4924 /* The frontend has worked out the size for us. */
4925 if (!loopspec[n]
4926 || !specinfo->shape
4927 || !integer_zerop (specinfo->start[spec_dim]))
4928 /* Prefer zero-based descriptors if possible. */
4929 loopspec[n] = ss;
4930 continue;
4933 if (ss_type == GFC_SS_CONSTRUCTOR)
4935 gfc_constructor_base base;
4936 /* An unknown size constructor will always be rank one.
4937 Higher rank constructors will either have known shape,
4938 or still be wrapped in a call to reshape. */
4939 gcc_assert (loop->dimen == 1);
4941 /* Always prefer to use the constructor bounds if the size
4942 can be determined at compile time. Prefer not to otherwise,
4943 since the general case involves realloc, and it's better to
4944 avoid that overhead if possible. */
4945 base = ss->info->expr->value.constructor;
4946 dynamic[n] = gfc_get_array_constructor_size (&i, base);
4947 if (!dynamic[n] || !loopspec[n])
4948 loopspec[n] = ss;
4949 continue;
4952 /* Avoid using an allocatable lhs in an assignment, since
4953 there might be a reallocation coming. */
4954 if (loopspec[n] && ss->is_alloc_lhs)
4955 continue;
4957 if (!loopspec[n])
4958 loopspec[n] = ss;
4959 /* Criteria for choosing a loop specifier (most important first):
4960 doesn't need realloc
4961 stride of one
4962 known stride
4963 known lower bound
4964 known upper bound
4966 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
4967 loopspec[n] = ss;
4968 else if (integer_onep (info->stride[dim])
4969 && !integer_onep (specinfo->stride[spec_dim]))
4970 loopspec[n] = ss;
4971 else if (INTEGER_CST_P (info->stride[dim])
4972 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
4973 loopspec[n] = ss;
4974 else if (INTEGER_CST_P (info->start[dim])
4975 && !INTEGER_CST_P (specinfo->start[spec_dim])
4976 && integer_onep (info->stride[dim])
4977 == integer_onep (specinfo->stride[spec_dim])
4978 && INTEGER_CST_P (info->stride[dim])
4979 == INTEGER_CST_P (specinfo->stride[spec_dim]))
4980 loopspec[n] = ss;
4981 /* We don't work out the upper bound.
4982 else if (INTEGER_CST_P (info->finish[n])
4983 && ! INTEGER_CST_P (specinfo->finish[n]))
4984 loopspec[n] = ss; */
4987 /* We should have found the scalarization loop specifier. If not,
4988 that's bad news. */
4989 gcc_assert (loopspec[n]);
4991 info = &loopspec[n]->info->data.array;
4992 dim = loopspec[n]->dim[n];
4994 /* Set the extents of this range. */
4995 cshape = info->shape;
4996 if (cshape && INTEGER_CST_P (info->start[dim])
4997 && INTEGER_CST_P (info->stride[dim]))
4999 loop->from[n] = info->start[dim];
5000 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
5001 mpz_sub_ui (i, i, 1);
5002 /* To = from + (size - 1) * stride. */
5003 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
5004 if (!integer_onep (info->stride[dim]))
5005 tmp = fold_build2_loc (input_location, MULT_EXPR,
5006 gfc_array_index_type, tmp,
5007 info->stride[dim]);
5008 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
5009 gfc_array_index_type,
5010 loop->from[n], tmp);
5012 else
5014 loop->from[n] = info->start[dim];
5015 switch (loopspec[n]->info->type)
5017 case GFC_SS_CONSTRUCTOR:
5018 /* The upper bound is calculated when we expand the
5019 constructor. */
5020 gcc_assert (loop->to[n] == NULL_TREE);
5021 break;
5023 case GFC_SS_SECTION:
5024 /* Use the end expression if it exists and is not constant,
5025 so that it is only evaluated once. */
5026 loop->to[n] = info->end[dim];
5027 break;
5029 case GFC_SS_FUNCTION:
5030 /* The loop bound will be set when we generate the call. */
5031 gcc_assert (loop->to[n] == NULL_TREE);
5032 break;
5034 case GFC_SS_INTRINSIC:
5036 gfc_expr *expr = loopspec[n]->info->expr;
5038 /* The {l,u}bound of an assumed rank. */
5039 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
5040 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
5041 && expr->value.function.actual->next->expr == NULL
5042 && expr->value.function.actual->expr->rank == -1);
5044 loop->to[n] = info->end[dim];
5045 break;
5048 case GFC_SS_COMPONENT:
5050 if (info->end[dim] != NULL_TREE)
5052 loop->to[n] = info->end[dim];
5053 break;
5055 else
5056 gcc_unreachable ();
5059 default:
5060 gcc_unreachable ();
5064 /* Transform everything so we have a simple incrementing variable. */
5065 if (integer_onep (info->stride[dim]))
5066 info->delta[dim] = gfc_index_zero_node;
5067 else
5069 /* Set the delta for this section. */
5070 info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre);
5071 /* Number of iterations is (end - start + step) / step.
5072 with start = 0, this simplifies to
5073 last = end / step;
5074 for (i = 0; i<=last; i++){...}; */
5075 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5076 gfc_array_index_type, loop->to[n],
5077 loop->from[n]);
5078 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
5079 gfc_array_index_type, tmp, info->stride[dim]);
5080 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5081 tmp, build_int_cst (gfc_array_index_type, -1));
5082 loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre);
5083 /* Make the loop variable start at 0. */
5084 loop->from[n] = gfc_index_zero_node;
5087 mpz_clear (i);
5089 for (loop = loop->nested; loop; loop = loop->next)
5090 set_loop_bounds (loop);
5094 /* Initialize the scalarization loop. Creates the loop variables. Determines
5095 the range of the loop variables. Creates a temporary if required.
5096 Also generates code for scalar expressions which have been
5097 moved outside the loop. */
5099 void
5100 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
5102 gfc_ss *tmp_ss;
5103 tree tmp;
5105 set_loop_bounds (loop);
5107 /* Add all the scalar code that can be taken out of the loops.
5108 This may include calculating the loop bounds, so do it before
5109 allocating the temporary. */
5110 gfc_add_loop_ss_code (loop, loop->ss, false, where);
5112 tmp_ss = loop->temp_ss;
5113 /* If we want a temporary then create it. */
5114 if (tmp_ss != NULL)
5116 gfc_ss_info *tmp_ss_info;
5118 tmp_ss_info = tmp_ss->info;
5119 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
5120 gcc_assert (loop->parent == NULL);
5122 /* Make absolutely sure that this is a complete type. */
5123 if (tmp_ss_info->string_length)
5124 tmp_ss_info->data.temp.type
5125 = gfc_get_character_type_len_for_eltype
5126 (TREE_TYPE (tmp_ss_info->data.temp.type),
5127 tmp_ss_info->string_length);
5129 tmp = tmp_ss_info->data.temp.type;
5130 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
5131 tmp_ss_info->type = GFC_SS_SECTION;
5133 gcc_assert (tmp_ss->dimen != 0);
5135 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
5136 NULL_TREE, false, true, false, where);
5139 /* For array parameters we don't have loop variables, so don't calculate the
5140 translations. */
5141 if (!loop->array_parameter)
5142 gfc_set_delta (loop);
5146 /* Calculates how to transform from loop variables to array indices for each
5147 array: once loop bounds are chosen, sets the difference (DELTA field) between
5148 loop bounds and array reference bounds, for each array info. */
5150 void
5151 gfc_set_delta (gfc_loopinfo *loop)
5153 gfc_ss *ss, **loopspec;
5154 gfc_array_info *info;
5155 tree tmp;
5156 int n, dim;
5158 gfc_loopinfo * const outer_loop = outermost_loop (loop);
5160 loopspec = loop->specloop;
5162 /* Calculate the translation from loop variables to array indices. */
5163 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
5165 gfc_ss_type ss_type;
5167 ss_type = ss->info->type;
5168 if (ss_type != GFC_SS_SECTION
5169 && ss_type != GFC_SS_COMPONENT
5170 && ss_type != GFC_SS_CONSTRUCTOR)
5171 continue;
5173 info = &ss->info->data.array;
5175 for (n = 0; n < ss->dimen; n++)
5177 /* If we are specifying the range the delta is already set. */
5178 if (loopspec[n] != ss)
5180 dim = ss->dim[n];
5182 /* Calculate the offset relative to the loop variable.
5183 First multiply by the stride. */
5184 tmp = loop->from[n];
5185 if (!integer_onep (info->stride[dim]))
5186 tmp = fold_build2_loc (input_location, MULT_EXPR,
5187 gfc_array_index_type,
5188 tmp, info->stride[dim]);
5190 /* Then subtract this from our starting value. */
5191 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5192 gfc_array_index_type,
5193 info->start[dim], tmp);
5195 info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
5200 for (loop = loop->nested; loop; loop = loop->next)
5201 gfc_set_delta (loop);
5205 /* Calculate the size of a given array dimension from the bounds. This
5206 is simply (ubound - lbound + 1) if this expression is positive
5207 or 0 if it is negative (pick either one if it is zero). Optionally
5208 (if or_expr is present) OR the (expression != 0) condition to it. */
5210 tree
5211 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
5213 tree res;
5214 tree cond;
5216 /* Calculate (ubound - lbound + 1). */
5217 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5218 ubound, lbound);
5219 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
5220 gfc_index_one_node);
5222 /* Check whether the size for this dimension is negative. */
5223 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, res,
5224 gfc_index_zero_node);
5225 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
5226 gfc_index_zero_node, res);
5228 /* Build OR expression. */
5229 if (or_expr)
5230 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
5231 logical_type_node, *or_expr, cond);
5233 return res;
5237 /* For an array descriptor, get the total number of elements. This is just
5238 the product of the extents along from_dim to to_dim. */
5240 static tree
5241 gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
5243 tree res;
5244 int dim;
5246 res = gfc_index_one_node;
5248 for (dim = from_dim; dim < to_dim; ++dim)
5250 tree lbound;
5251 tree ubound;
5252 tree extent;
5254 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
5255 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
5257 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
5258 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5259 res, extent);
5262 return res;
5266 /* Full size of an array. */
5268 tree
5269 gfc_conv_descriptor_size (tree desc, int rank)
5271 return gfc_conv_descriptor_size_1 (desc, 0, rank);
5275 /* Size of a coarray for all dimensions but the last. */
5277 tree
5278 gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
5280 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
5284 /* Fills in an array descriptor, and returns the size of the array.
5285 The size will be a simple_val, ie a variable or a constant. Also
5286 calculates the offset of the base. The pointer argument overflow,
5287 which should be of integer type, will increase in value if overflow
5288 occurs during the size calculation. Returns the size of the array.
5290 stride = 1;
5291 offset = 0;
5292 for (n = 0; n < rank; n++)
5294 a.lbound[n] = specified_lower_bound;
5295 offset = offset + a.lbond[n] * stride;
5296 size = 1 - lbound;
5297 a.ubound[n] = specified_upper_bound;
5298 a.stride[n] = stride;
5299 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
5300 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
5301 stride = stride * size;
5303 for (n = rank; n < rank+corank; n++)
5304 (Set lcobound/ucobound as above.)
5305 element_size = sizeof (array element);
5306 if (!rank)
5307 return element_size
5308 stride = (size_t) stride;
5309 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
5310 stride = stride * element_size;
5311 return (stride);
5312 } */
5313 /*GCC ARRAYS*/
5315 static tree
5316 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
5317 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
5318 stmtblock_t * descriptor_block, tree * overflow,
5319 tree expr3_elem_size, tree *nelems, gfc_expr *expr3,
5320 tree expr3_desc, bool e3_is_array_constr, gfc_expr *expr)
5322 tree type;
5323 tree tmp;
5324 tree size;
5325 tree offset;
5326 tree stride;
5327 tree element_size;
5328 tree or_expr;
5329 tree thencase;
5330 tree elsecase;
5331 tree cond;
5332 tree var;
5333 stmtblock_t thenblock;
5334 stmtblock_t elseblock;
5335 gfc_expr *ubound;
5336 gfc_se se;
5337 int n;
5339 type = TREE_TYPE (descriptor);
5341 stride = gfc_index_one_node;
5342 offset = gfc_index_zero_node;
5344 /* Set the dtype before the alloc, because registration of coarrays needs
5345 it initialized. */
5346 if (expr->ts.type == BT_CHARACTER
5347 && expr->ts.deferred
5348 && VAR_P (expr->ts.u.cl->backend_decl))
5350 type = gfc_typenode_for_spec (&expr->ts);
5351 tmp = gfc_conv_descriptor_dtype (descriptor);
5352 gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type));
5354 else
5356 tmp = gfc_conv_descriptor_dtype (descriptor);
5357 gfc_add_modify (pblock, tmp, gfc_get_dtype (type));
5360 or_expr = logical_false_node;
5362 for (n = 0; n < rank; n++)
5364 tree conv_lbound;
5365 tree conv_ubound;
5367 /* We have 3 possibilities for determining the size of the array:
5368 lower == NULL => lbound = 1, ubound = upper[n]
5369 upper[n] = NULL => lbound = 1, ubound = lower[n]
5370 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
5371 ubound = upper[n];
5373 /* Set lower bound. */
5374 gfc_init_se (&se, NULL);
5375 if (expr3_desc != NULL_TREE)
5377 if (e3_is_array_constr)
5378 /* The lbound of a constant array [] starts at zero, but when
5379 allocating it, the standard expects the array to start at
5380 one. */
5381 se.expr = gfc_index_one_node;
5382 else
5383 se.expr = gfc_conv_descriptor_lbound_get (expr3_desc,
5384 gfc_rank_cst[n]);
5386 else if (lower == NULL)
5387 se.expr = gfc_index_one_node;
5388 else
5390 gcc_assert (lower[n]);
5391 if (ubound)
5393 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5394 gfc_add_block_to_block (pblock, &se.pre);
5396 else
5398 se.expr = gfc_index_one_node;
5399 ubound = lower[n];
5402 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5403 gfc_rank_cst[n], se.expr);
5404 conv_lbound = se.expr;
5406 /* Work out the offset for this component. */
5407 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5408 se.expr, stride);
5409 offset = fold_build2_loc (input_location, MINUS_EXPR,
5410 gfc_array_index_type, offset, tmp);
5412 /* Set upper bound. */
5413 gfc_init_se (&se, NULL);
5414 if (expr3_desc != NULL_TREE)
5416 if (e3_is_array_constr)
5418 /* The lbound of a constant array [] starts at zero, but when
5419 allocating it, the standard expects the array to start at
5420 one. Therefore fix the upper bound to be
5421 (desc.ubound - desc.lbound)+ 1. */
5422 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5423 gfc_array_index_type,
5424 gfc_conv_descriptor_ubound_get (
5425 expr3_desc, gfc_rank_cst[n]),
5426 gfc_conv_descriptor_lbound_get (
5427 expr3_desc, gfc_rank_cst[n]));
5428 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5429 gfc_array_index_type, tmp,
5430 gfc_index_one_node);
5431 se.expr = gfc_evaluate_now (tmp, pblock);
5433 else
5434 se.expr = gfc_conv_descriptor_ubound_get (expr3_desc,
5435 gfc_rank_cst[n]);
5437 else
5439 gcc_assert (ubound);
5440 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5441 gfc_add_block_to_block (pblock, &se.pre);
5442 if (ubound->expr_type == EXPR_FUNCTION)
5443 se.expr = gfc_evaluate_now (se.expr, pblock);
5445 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
5446 gfc_rank_cst[n], se.expr);
5447 conv_ubound = se.expr;
5449 /* Store the stride. */
5450 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
5451 gfc_rank_cst[n], stride);
5453 /* Calculate size and check whether extent is negative. */
5454 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
5455 size = gfc_evaluate_now (size, pblock);
5457 /* Check whether multiplying the stride by the number of
5458 elements in this dimension would overflow. We must also check
5459 whether the current dimension has zero size in order to avoid
5460 division by zero.
5462 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5463 gfc_array_index_type,
5464 fold_convert (gfc_array_index_type,
5465 TYPE_MAX_VALUE (gfc_array_index_type)),
5466 size);
5467 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5468 logical_type_node, tmp, stride),
5469 PRED_FORTRAN_OVERFLOW);
5470 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5471 integer_one_node, integer_zero_node);
5472 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5473 logical_type_node, size,
5474 gfc_index_zero_node),
5475 PRED_FORTRAN_SIZE_ZERO);
5476 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5477 integer_zero_node, tmp);
5478 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5479 *overflow, tmp);
5480 *overflow = gfc_evaluate_now (tmp, pblock);
5482 /* Multiply the stride by the number of elements in this dimension. */
5483 stride = fold_build2_loc (input_location, MULT_EXPR,
5484 gfc_array_index_type, stride, size);
5485 stride = gfc_evaluate_now (stride, pblock);
5488 for (n = rank; n < rank + corank; n++)
5490 ubound = upper[n];
5492 /* Set lower bound. */
5493 gfc_init_se (&se, NULL);
5494 if (lower == NULL || lower[n] == NULL)
5496 gcc_assert (n == rank + corank - 1);
5497 se.expr = gfc_index_one_node;
5499 else
5501 if (ubound || n == rank + corank - 1)
5503 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5504 gfc_add_block_to_block (pblock, &se.pre);
5506 else
5508 se.expr = gfc_index_one_node;
5509 ubound = lower[n];
5512 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5513 gfc_rank_cst[n], se.expr);
5515 if (n < rank + corank - 1)
5517 gfc_init_se (&se, NULL);
5518 gcc_assert (ubound);
5519 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5520 gfc_add_block_to_block (pblock, &se.pre);
5521 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
5522 gfc_rank_cst[n], se.expr);
5526 /* The stride is the number of elements in the array, so multiply by the
5527 size of an element to get the total size. Obviously, if there is a
5528 SOURCE expression (expr3) we must use its element size. */
5529 if (expr3_elem_size != NULL_TREE)
5530 tmp = expr3_elem_size;
5531 else if (expr3 != NULL)
5533 if (expr3->ts.type == BT_CLASS)
5535 gfc_se se_sz;
5536 gfc_expr *sz = gfc_copy_expr (expr3);
5537 gfc_add_vptr_component (sz);
5538 gfc_add_size_component (sz);
5539 gfc_init_se (&se_sz, NULL);
5540 gfc_conv_expr (&se_sz, sz);
5541 gfc_free_expr (sz);
5542 tmp = se_sz.expr;
5544 else
5546 tmp = gfc_typenode_for_spec (&expr3->ts);
5547 tmp = TYPE_SIZE_UNIT (tmp);
5550 else
5551 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5553 /* Convert to size_t. */
5554 element_size = fold_convert (size_type_node, tmp);
5556 if (rank == 0)
5557 return element_size;
5559 *nelems = gfc_evaluate_now (stride, pblock);
5560 stride = fold_convert (size_type_node, stride);
5562 /* First check for overflow. Since an array of type character can
5563 have zero element_size, we must check for that before
5564 dividing. */
5565 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5566 size_type_node,
5567 TYPE_MAX_VALUE (size_type_node), element_size);
5568 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5569 logical_type_node, tmp, stride),
5570 PRED_FORTRAN_OVERFLOW);
5571 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5572 integer_one_node, integer_zero_node);
5573 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5574 logical_type_node, element_size,
5575 build_int_cst (size_type_node, 0)),
5576 PRED_FORTRAN_SIZE_ZERO);
5577 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5578 integer_zero_node, tmp);
5579 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5580 *overflow, tmp);
5581 *overflow = gfc_evaluate_now (tmp, pblock);
5583 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
5584 stride, element_size);
5586 if (poffset != NULL)
5588 offset = gfc_evaluate_now (offset, pblock);
5589 *poffset = offset;
5592 if (integer_zerop (or_expr))
5593 return size;
5594 if (integer_onep (or_expr))
5595 return build_int_cst (size_type_node, 0);
5597 var = gfc_create_var (TREE_TYPE (size), "size");
5598 gfc_start_block (&thenblock);
5599 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
5600 thencase = gfc_finish_block (&thenblock);
5602 gfc_start_block (&elseblock);
5603 gfc_add_modify (&elseblock, var, size);
5604 elsecase = gfc_finish_block (&elseblock);
5606 tmp = gfc_evaluate_now (or_expr, pblock);
5607 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
5608 gfc_add_expr_to_block (pblock, tmp);
5610 return var;
5614 /* Retrieve the last ref from the chain. This routine is specific to
5615 gfc_array_allocate ()'s needs. */
5617 bool
5618 retrieve_last_ref (gfc_ref **ref_in, gfc_ref **prev_ref_in)
5620 gfc_ref *ref, *prev_ref;
5622 ref = *ref_in;
5623 /* Prevent warnings for uninitialized variables. */
5624 prev_ref = *prev_ref_in;
5625 while (ref && ref->next != NULL)
5627 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
5628 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
5629 prev_ref = ref;
5630 ref = ref->next;
5633 if (ref == NULL || ref->type != REF_ARRAY)
5634 return false;
5636 *ref_in = ref;
5637 *prev_ref_in = prev_ref;
5638 return true;
5641 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
5642 the work for an ALLOCATE statement. */
5643 /*GCC ARRAYS*/
5645 bool
5646 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
5647 tree errlen, tree label_finish, tree expr3_elem_size,
5648 tree *nelems, gfc_expr *expr3, tree e3_arr_desc,
5649 bool e3_is_array_constr)
5651 tree tmp;
5652 tree pointer;
5653 tree offset = NULL_TREE;
5654 tree token = NULL_TREE;
5655 tree size;
5656 tree msg;
5657 tree error = NULL_TREE;
5658 tree overflow; /* Boolean storing whether size calculation overflows. */
5659 tree var_overflow = NULL_TREE;
5660 tree cond;
5661 tree set_descriptor;
5662 stmtblock_t set_descriptor_block;
5663 stmtblock_t elseblock;
5664 gfc_expr **lower;
5665 gfc_expr **upper;
5666 gfc_ref *ref, *prev_ref = NULL, *coref;
5667 bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false,
5668 non_ulimate_coarray_ptr_comp;
5670 ref = expr->ref;
5672 /* Find the last reference in the chain. */
5673 if (!retrieve_last_ref (&ref, &prev_ref))
5674 return false;
5676 /* Take the allocatable and coarray properties solely from the expr-ref's
5677 attributes and not from source=-expression. */
5678 if (!prev_ref)
5680 allocatable = expr->symtree->n.sym->attr.allocatable;
5681 dimension = expr->symtree->n.sym->attr.dimension;
5682 non_ulimate_coarray_ptr_comp = false;
5684 else
5686 allocatable = prev_ref->u.c.component->attr.allocatable;
5687 /* Pointer components in coarrayed derived types must be treated
5688 specially in that they are registered without a check if the are
5689 already associated. This does not hold for ultimate coarray
5690 pointers. */
5691 non_ulimate_coarray_ptr_comp = (prev_ref->u.c.component->attr.pointer
5692 && !prev_ref->u.c.component->attr.codimension);
5693 dimension = prev_ref->u.c.component->attr.dimension;
5696 /* For allocatable/pointer arrays in derived types, one of the refs has to be
5697 a coarray. In this case it does not matter whether we are on this_image
5698 or not. */
5699 coarray = false;
5700 for (coref = expr->ref; coref; coref = coref->next)
5701 if (coref->type == REF_ARRAY && coref->u.ar.codimen > 0)
5703 coarray = true;
5704 break;
5707 if (!dimension)
5708 gcc_assert (coarray);
5710 if (ref->u.ar.type == AR_FULL && expr3 != NULL)
5712 gfc_ref *old_ref = ref;
5713 /* F08:C633: Array shape from expr3. */
5714 ref = expr3->ref;
5716 /* Find the last reference in the chain. */
5717 if (!retrieve_last_ref (&ref, &prev_ref))
5719 if (expr3->expr_type == EXPR_FUNCTION
5720 && gfc_expr_attr (expr3).dimension)
5721 ref = old_ref;
5722 else
5723 return false;
5725 alloc_w_e3_arr_spec = true;
5728 /* Figure out the size of the array. */
5729 switch (ref->u.ar.type)
5731 case AR_ELEMENT:
5732 if (!coarray)
5734 lower = NULL;
5735 upper = ref->u.ar.start;
5736 break;
5738 /* Fall through. */
5740 case AR_SECTION:
5741 lower = ref->u.ar.start;
5742 upper = ref->u.ar.end;
5743 break;
5745 case AR_FULL:
5746 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT
5747 || alloc_w_e3_arr_spec);
5749 lower = ref->u.ar.as->lower;
5750 upper = ref->u.ar.as->upper;
5751 break;
5753 default:
5754 gcc_unreachable ();
5755 break;
5758 overflow = integer_zero_node;
5760 gfc_init_block (&set_descriptor_block);
5761 /* Take the corank only from the actual ref and not from the coref. The
5762 later will mislead the generation of the array dimensions for allocatable/
5763 pointer components in derived types. */
5764 size = gfc_array_init_size (se->expr, alloc_w_e3_arr_spec ? expr->rank
5765 : ref->u.ar.as->rank,
5766 coarray ? ref->u.ar.as->corank : 0,
5767 &offset, lower, upper,
5768 &se->pre, &set_descriptor_block, &overflow,
5769 expr3_elem_size, nelems, expr3, e3_arr_desc,
5770 e3_is_array_constr, expr);
5772 if (dimension)
5774 var_overflow = gfc_create_var (integer_type_node, "overflow");
5775 gfc_add_modify (&se->pre, var_overflow, overflow);
5777 if (status == NULL_TREE)
5779 /* Generate the block of code handling overflow. */
5780 msg = gfc_build_addr_expr (pchar_type_node,
5781 gfc_build_localized_cstring_const
5782 ("Integer overflow when calculating the amount of "
5783 "memory to allocate"));
5784 error = build_call_expr_loc (input_location,
5785 gfor_fndecl_runtime_error, 1, msg);
5787 else
5789 tree status_type = TREE_TYPE (status);
5790 stmtblock_t set_status_block;
5792 gfc_start_block (&set_status_block);
5793 gfc_add_modify (&set_status_block, status,
5794 build_int_cst (status_type, LIBERROR_ALLOCATION));
5795 error = gfc_finish_block (&set_status_block);
5799 gfc_start_block (&elseblock);
5801 /* Allocate memory to store the data. */
5802 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
5803 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
5805 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
5807 pointer = non_ulimate_coarray_ptr_comp ? se->expr
5808 : gfc_conv_descriptor_data_get (se->expr);
5809 token = gfc_conv_descriptor_token (se->expr);
5810 token = gfc_build_addr_expr (NULL_TREE, token);
5812 else
5813 pointer = gfc_conv_descriptor_data_get (se->expr);
5814 STRIP_NOPS (pointer);
5816 /* The allocatable variant takes the old pointer as first argument. */
5817 if (allocatable)
5818 gfc_allocate_allocatable (&elseblock, pointer, size, token,
5819 status, errmsg, errlen, label_finish, expr,
5820 coref != NULL ? coref->u.ar.as->corank : 0);
5821 else if (non_ulimate_coarray_ptr_comp && token)
5822 /* The token is set only for GFC_FCOARRAY_LIB mode. */
5823 gfc_allocate_using_caf_lib (&elseblock, pointer, size, token, status,
5824 errmsg, errlen,
5825 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY);
5826 else
5827 gfc_allocate_using_malloc (&elseblock, pointer, size, status);
5829 if (dimension)
5831 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
5832 logical_type_node, var_overflow, integer_zero_node),
5833 PRED_FORTRAN_OVERFLOW);
5834 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
5835 error, gfc_finish_block (&elseblock));
5837 else
5838 tmp = gfc_finish_block (&elseblock);
5840 gfc_add_expr_to_block (&se->pre, tmp);
5842 /* Update the array descriptors. */
5843 if (dimension)
5844 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
5846 /* Pointer arrays need the span field to be set. */
5847 if (is_pointer_array (se->expr)
5848 || (expr->ts.type == BT_CLASS
5849 && CLASS_DATA (expr)->attr.class_pointer))
5851 if (expr3 && expr3_elem_size != NULL_TREE)
5852 tmp = expr3_elem_size;
5853 else
5854 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (se->expr)));
5855 tmp = fold_convert (gfc_array_index_type, tmp);
5856 gfc_conv_descriptor_span_set (&set_descriptor_block, se->expr, tmp);
5859 set_descriptor = gfc_finish_block (&set_descriptor_block);
5860 if (status != NULL_TREE)
5862 cond = fold_build2_loc (input_location, EQ_EXPR,
5863 logical_type_node, status,
5864 build_int_cst (TREE_TYPE (status), 0));
5865 gfc_add_expr_to_block (&se->pre,
5866 fold_build3_loc (input_location, COND_EXPR, void_type_node,
5867 cond,
5868 set_descriptor,
5869 build_empty_stmt (input_location)));
5871 else
5872 gfc_add_expr_to_block (&se->pre, set_descriptor);
5874 return true;
5878 /* Create an array constructor from an initialization expression.
5879 We assume the frontend already did any expansions and conversions. */
5881 tree
5882 gfc_conv_array_initializer (tree type, gfc_expr * expr)
5884 gfc_constructor *c;
5885 tree tmp;
5886 offset_int wtmp;
5887 gfc_se se;
5888 tree index, range;
5889 vec<constructor_elt, va_gc> *v = NULL;
5891 if (expr->expr_type == EXPR_VARIABLE
5892 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
5893 && expr->symtree->n.sym->value)
5894 expr = expr->symtree->n.sym->value;
5896 switch (expr->expr_type)
5898 case EXPR_CONSTANT:
5899 case EXPR_STRUCTURE:
5900 /* A single scalar or derived type value. Create an array with all
5901 elements equal to that value. */
5902 gfc_init_se (&se, NULL);
5904 if (expr->expr_type == EXPR_CONSTANT)
5905 gfc_conv_constant (&se, expr);
5906 else
5907 gfc_conv_structure (&se, expr, 1);
5909 wtmp = wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1;
5910 /* This will probably eat buckets of memory for large arrays. */
5911 while (wtmp != 0)
5913 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
5914 wtmp -= 1;
5916 break;
5918 case EXPR_ARRAY:
5919 /* Create a vector of all the elements. */
5920 for (c = gfc_constructor_first (expr->value.constructor);
5921 c; c = gfc_constructor_next (c))
5923 if (c->iterator)
5925 /* Problems occur when we get something like
5926 integer :: a(lots) = (/(i, i=1, lots)/) */
5927 gfc_fatal_error ("The number of elements in the array "
5928 "constructor at %L requires an increase of "
5929 "the allowed %d upper limit. See "
5930 "%<-fmax-array-constructor%> option",
5931 &expr->where, flag_max_array_constructor);
5932 return NULL_TREE;
5934 if (mpz_cmp_si (c->offset, 0) != 0)
5935 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5936 else
5937 index = NULL_TREE;
5939 if (mpz_cmp_si (c->repeat, 1) > 0)
5941 tree tmp1, tmp2;
5942 mpz_t maxval;
5944 mpz_init (maxval);
5945 mpz_add (maxval, c->offset, c->repeat);
5946 mpz_sub_ui (maxval, maxval, 1);
5947 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5948 if (mpz_cmp_si (c->offset, 0) != 0)
5950 mpz_add_ui (maxval, c->offset, 1);
5951 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5953 else
5954 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5956 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
5957 mpz_clear (maxval);
5959 else
5960 range = NULL;
5962 gfc_init_se (&se, NULL);
5963 switch (c->expr->expr_type)
5965 case EXPR_CONSTANT:
5966 gfc_conv_constant (&se, c->expr);
5967 break;
5969 case EXPR_STRUCTURE:
5970 gfc_conv_structure (&se, c->expr, 1);
5971 break;
5973 default:
5974 /* Catch those occasional beasts that do not simplify
5975 for one reason or another, assuming that if they are
5976 standard defying the frontend will catch them. */
5977 gfc_conv_expr (&se, c->expr);
5978 break;
5981 if (range == NULL_TREE)
5982 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5983 else
5985 if (index != NULL_TREE)
5986 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5987 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
5990 break;
5992 case EXPR_NULL:
5993 return gfc_build_null_descriptor (type);
5995 default:
5996 gcc_unreachable ();
5999 /* Create a constructor from the list of elements. */
6000 tmp = build_constructor (type, v);
6001 TREE_CONSTANT (tmp) = 1;
6002 return tmp;
6006 /* Generate code to evaluate non-constant coarray cobounds. */
6008 void
6009 gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
6010 const gfc_symbol *sym)
6012 int dim;
6013 tree ubound;
6014 tree lbound;
6015 gfc_se se;
6016 gfc_array_spec *as;
6018 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6020 for (dim = as->rank; dim < as->rank + as->corank; dim++)
6022 /* Evaluate non-constant array bound expressions. */
6023 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6024 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6026 gfc_init_se (&se, NULL);
6027 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6028 gfc_add_block_to_block (pblock, &se.pre);
6029 gfc_add_modify (pblock, lbound, se.expr);
6031 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6032 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6034 gfc_init_se (&se, NULL);
6035 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6036 gfc_add_block_to_block (pblock, &se.pre);
6037 gfc_add_modify (pblock, ubound, se.expr);
6043 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
6044 returns the size (in elements) of the array. */
6046 static tree
6047 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
6048 stmtblock_t * pblock)
6050 gfc_array_spec *as;
6051 tree size;
6052 tree stride;
6053 tree offset;
6054 tree ubound;
6055 tree lbound;
6056 tree tmp;
6057 gfc_se se;
6059 int dim;
6061 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6063 size = gfc_index_one_node;
6064 offset = gfc_index_zero_node;
6065 for (dim = 0; dim < as->rank; dim++)
6067 /* Evaluate non-constant array bound expressions. */
6068 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
6069 if (as->lower[dim] && !INTEGER_CST_P (lbound))
6071 gfc_init_se (&se, NULL);
6072 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
6073 gfc_add_block_to_block (pblock, &se.pre);
6074 gfc_add_modify (pblock, lbound, se.expr);
6076 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
6077 if (as->upper[dim] && !INTEGER_CST_P (ubound))
6079 gfc_init_se (&se, NULL);
6080 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
6081 gfc_add_block_to_block (pblock, &se.pre);
6082 gfc_add_modify (pblock, ubound, se.expr);
6084 /* The offset of this dimension. offset = offset - lbound * stride. */
6085 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6086 lbound, size);
6087 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6088 offset, tmp);
6090 /* The size of this dimension, and the stride of the next. */
6091 if (dim + 1 < as->rank)
6092 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
6093 else
6094 stride = GFC_TYPE_ARRAY_SIZE (type);
6096 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
6098 /* Calculate stride = size * (ubound + 1 - lbound). */
6099 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6100 gfc_array_index_type,
6101 gfc_index_one_node, lbound);
6102 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6103 gfc_array_index_type, ubound, tmp);
6104 tmp = fold_build2_loc (input_location, MULT_EXPR,
6105 gfc_array_index_type, size, tmp);
6106 if (stride)
6107 gfc_add_modify (pblock, stride, tmp);
6108 else
6109 stride = gfc_evaluate_now (tmp, pblock);
6111 /* Make sure that negative size arrays are translated
6112 to being zero size. */
6113 tmp = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
6114 stride, gfc_index_zero_node);
6115 tmp = fold_build3_loc (input_location, COND_EXPR,
6116 gfc_array_index_type, tmp,
6117 stride, gfc_index_zero_node);
6118 gfc_add_modify (pblock, stride, tmp);
6121 size = stride;
6124 gfc_trans_array_cobounds (type, pblock, sym);
6125 gfc_trans_vla_type_sizes (sym, pblock);
6127 *poffset = offset;
6128 return size;
6132 /* Generate code to initialize/allocate an array variable. */
6134 void
6135 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
6136 gfc_wrapped_block * block)
6138 stmtblock_t init;
6139 tree type;
6140 tree tmp = NULL_TREE;
6141 tree size;
6142 tree offset;
6143 tree space;
6144 tree inittree;
6145 bool onstack;
6147 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
6149 /* Do nothing for USEd variables. */
6150 if (sym->attr.use_assoc)
6151 return;
6153 type = TREE_TYPE (decl);
6154 gcc_assert (GFC_ARRAY_TYPE_P (type));
6155 onstack = TREE_CODE (type) != POINTER_TYPE;
6157 gfc_init_block (&init);
6159 /* Evaluate character string length. */
6160 if (sym->ts.type == BT_CHARACTER
6161 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6163 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6165 gfc_trans_vla_type_sizes (sym, &init);
6167 /* Emit a DECL_EXPR for this variable, which will cause the
6168 gimplifier to allocate storage, and all that good stuff. */
6169 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
6170 gfc_add_expr_to_block (&init, tmp);
6173 if (onstack)
6175 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6176 return;
6179 type = TREE_TYPE (type);
6181 gcc_assert (!sym->attr.use_assoc);
6182 gcc_assert (!TREE_STATIC (decl));
6183 gcc_assert (!sym->module);
6185 if (sym->ts.type == BT_CHARACTER
6186 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
6187 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6189 size = gfc_trans_array_bounds (type, sym, &offset, &init);
6191 /* Don't actually allocate space for Cray Pointees. */
6192 if (sym->attr.cray_pointee)
6194 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6195 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6197 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6198 return;
6201 if (flag_stack_arrays)
6203 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
6204 space = build_decl (sym->declared_at.lb->location,
6205 VAR_DECL, create_tmp_var_name ("A"),
6206 TREE_TYPE (TREE_TYPE (decl)));
6207 gfc_trans_vla_type_sizes (sym, &init);
6209 else
6211 /* The size is the number of elements in the array, so multiply by the
6212 size of an element to get the total size. */
6213 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
6214 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6215 size, fold_convert (gfc_array_index_type, tmp));
6217 /* Allocate memory to hold the data. */
6218 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
6219 gfc_add_modify (&init, decl, tmp);
6221 /* Free the temporary. */
6222 tmp = gfc_call_free (decl);
6223 space = NULL_TREE;
6226 /* Set offset of the array. */
6227 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6228 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6230 /* Automatic arrays should not have initializers. */
6231 gcc_assert (!sym->value);
6233 inittree = gfc_finish_block (&init);
6235 if (space)
6237 tree addr;
6238 pushdecl (space);
6240 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
6241 where also space is located. */
6242 gfc_init_block (&init);
6243 tmp = fold_build1_loc (input_location, DECL_EXPR,
6244 TREE_TYPE (space), space);
6245 gfc_add_expr_to_block (&init, tmp);
6246 addr = fold_build1_loc (sym->declared_at.lb->location,
6247 ADDR_EXPR, TREE_TYPE (decl), space);
6248 gfc_add_modify (&init, decl, addr);
6249 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
6250 tmp = NULL_TREE;
6252 gfc_add_init_cleanup (block, inittree, tmp);
6256 /* Generate entry and exit code for g77 calling convention arrays. */
6258 void
6259 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
6261 tree parm;
6262 tree type;
6263 locus loc;
6264 tree offset;
6265 tree tmp;
6266 tree stmt;
6267 stmtblock_t init;
6269 gfc_save_backend_locus (&loc);
6270 gfc_set_backend_locus (&sym->declared_at);
6272 /* Descriptor type. */
6273 parm = sym->backend_decl;
6274 type = TREE_TYPE (parm);
6275 gcc_assert (GFC_ARRAY_TYPE_P (type));
6277 gfc_start_block (&init);
6279 if (sym->ts.type == BT_CHARACTER
6280 && VAR_P (sym->ts.u.cl->backend_decl))
6281 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6283 /* Evaluate the bounds of the array. */
6284 gfc_trans_array_bounds (type, sym, &offset, &init);
6286 /* Set the offset. */
6287 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6288 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6290 /* Set the pointer itself if we aren't using the parameter directly. */
6291 if (TREE_CODE (parm) != PARM_DECL)
6293 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
6294 gfc_add_modify (&init, parm, tmp);
6296 stmt = gfc_finish_block (&init);
6298 gfc_restore_backend_locus (&loc);
6300 /* Add the initialization code to the start of the function. */
6302 if (sym->attr.optional || sym->attr.not_always_present)
6304 tmp = gfc_conv_expr_present (sym);
6305 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
6308 gfc_add_init_cleanup (block, stmt, NULL_TREE);
6312 /* Modify the descriptor of an array parameter so that it has the
6313 correct lower bound. Also move the upper bound accordingly.
6314 If the array is not packed, it will be copied into a temporary.
6315 For each dimension we set the new lower and upper bounds. Then we copy the
6316 stride and calculate the offset for this dimension. We also work out
6317 what the stride of a packed array would be, and see it the two match.
6318 If the array need repacking, we set the stride to the values we just
6319 calculated, recalculate the offset and copy the array data.
6320 Code is also added to copy the data back at the end of the function.
6323 void
6324 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
6325 gfc_wrapped_block * block)
6327 tree size;
6328 tree type;
6329 tree offset;
6330 locus loc;
6331 stmtblock_t init;
6332 tree stmtInit, stmtCleanup;
6333 tree lbound;
6334 tree ubound;
6335 tree dubound;
6336 tree dlbound;
6337 tree dumdesc;
6338 tree tmp;
6339 tree stride, stride2;
6340 tree stmt_packed;
6341 tree stmt_unpacked;
6342 tree partial;
6343 gfc_se se;
6344 int n;
6345 int checkparm;
6346 int no_repack;
6347 bool optional_arg;
6348 gfc_array_spec *as;
6349 bool is_classarray = IS_CLASS_ARRAY (sym);
6351 /* Do nothing for pointer and allocatable arrays. */
6352 if ((sym->ts.type != BT_CLASS && sym->attr.pointer)
6353 || (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.class_pointer)
6354 || sym->attr.allocatable
6355 || (is_classarray && CLASS_DATA (sym)->attr.allocatable))
6356 return;
6358 if (!is_classarray && sym->attr.dummy && gfc_is_nodesc_array (sym))
6360 gfc_trans_g77_array (sym, block);
6361 return;
6364 loc.nextc = NULL;
6365 gfc_save_backend_locus (&loc);
6366 /* loc.nextc is not set by save_backend_locus but the location routines
6367 depend on it. */
6368 if (loc.nextc == NULL)
6369 loc.nextc = loc.lb->line;
6370 gfc_set_backend_locus (&sym->declared_at);
6372 /* Descriptor type. */
6373 type = TREE_TYPE (tmpdesc);
6374 gcc_assert (GFC_ARRAY_TYPE_P (type));
6375 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6376 if (is_classarray)
6377 /* For a class array the dummy array descriptor is in the _class
6378 component. */
6379 dumdesc = gfc_class_data_get (dumdesc);
6380 else
6381 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
6382 as = IS_CLASS_ARRAY (sym) ? CLASS_DATA (sym)->as : sym->as;
6383 gfc_start_block (&init);
6385 if (sym->ts.type == BT_CHARACTER
6386 && VAR_P (sym->ts.u.cl->backend_decl))
6387 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
6389 checkparm = (as->type == AS_EXPLICIT
6390 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
6392 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
6393 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
6395 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
6397 /* For non-constant shape arrays we only check if the first dimension
6398 is contiguous. Repacking higher dimensions wouldn't gain us
6399 anything as we still don't know the array stride. */
6400 partial = gfc_create_var (logical_type_node, "partial");
6401 TREE_USED (partial) = 1;
6402 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
6403 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, tmp,
6404 gfc_index_one_node);
6405 gfc_add_modify (&init, partial, tmp);
6407 else
6408 partial = NULL_TREE;
6410 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
6411 here, however I think it does the right thing. */
6412 if (no_repack)
6414 /* Set the first stride. */
6415 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
6416 stride = gfc_evaluate_now (stride, &init);
6418 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
6419 stride, gfc_index_zero_node);
6420 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
6421 tmp, gfc_index_one_node, stride);
6422 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
6423 gfc_add_modify (&init, stride, tmp);
6425 /* Allow the user to disable array repacking. */
6426 stmt_unpacked = NULL_TREE;
6428 else
6430 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
6431 /* A library call to repack the array if necessary. */
6432 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6433 stmt_unpacked = build_call_expr_loc (input_location,
6434 gfor_fndecl_in_pack, 1, tmp);
6436 stride = gfc_index_one_node;
6438 if (warn_array_temporaries)
6439 gfc_warning (OPT_Warray_temporaries,
6440 "Creating array temporary at %L", &loc);
6443 /* This is for the case where the array data is used directly without
6444 calling the repack function. */
6445 if (no_repack || partial != NULL_TREE)
6446 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
6447 else
6448 stmt_packed = NULL_TREE;
6450 /* Assign the data pointer. */
6451 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6453 /* Don't repack unknown shape arrays when the first stride is 1. */
6454 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
6455 partial, stmt_packed, stmt_unpacked);
6457 else
6458 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
6459 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
6461 offset = gfc_index_zero_node;
6462 size = gfc_index_one_node;
6464 /* Evaluate the bounds of the array. */
6465 for (n = 0; n < as->rank; n++)
6467 if (checkparm || !as->upper[n])
6469 /* Get the bounds of the actual parameter. */
6470 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
6471 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
6473 else
6475 dubound = NULL_TREE;
6476 dlbound = NULL_TREE;
6479 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
6480 if (!INTEGER_CST_P (lbound))
6482 gfc_init_se (&se, NULL);
6483 gfc_conv_expr_type (&se, as->lower[n],
6484 gfc_array_index_type);
6485 gfc_add_block_to_block (&init, &se.pre);
6486 gfc_add_modify (&init, lbound, se.expr);
6489 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
6490 /* Set the desired upper bound. */
6491 if (as->upper[n])
6493 /* We know what we want the upper bound to be. */
6494 if (!INTEGER_CST_P (ubound))
6496 gfc_init_se (&se, NULL);
6497 gfc_conv_expr_type (&se, as->upper[n],
6498 gfc_array_index_type);
6499 gfc_add_block_to_block (&init, &se.pre);
6500 gfc_add_modify (&init, ubound, se.expr);
6503 /* Check the sizes match. */
6504 if (checkparm)
6506 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
6507 char * msg;
6508 tree temp;
6510 temp = fold_build2_loc (input_location, MINUS_EXPR,
6511 gfc_array_index_type, ubound, lbound);
6512 temp = fold_build2_loc (input_location, PLUS_EXPR,
6513 gfc_array_index_type,
6514 gfc_index_one_node, temp);
6515 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
6516 gfc_array_index_type, dubound,
6517 dlbound);
6518 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
6519 gfc_array_index_type,
6520 gfc_index_one_node, stride2);
6521 tmp = fold_build2_loc (input_location, NE_EXPR,
6522 gfc_array_index_type, temp, stride2);
6523 msg = xasprintf ("Dimension %d of array '%s' has extent "
6524 "%%ld instead of %%ld", n+1, sym->name);
6526 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
6527 fold_convert (long_integer_type_node, temp),
6528 fold_convert (long_integer_type_node, stride2));
6530 free (msg);
6533 else
6535 /* For assumed shape arrays move the upper bound by the same amount
6536 as the lower bound. */
6537 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6538 gfc_array_index_type, dubound, dlbound);
6539 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6540 gfc_array_index_type, tmp, lbound);
6541 gfc_add_modify (&init, ubound, tmp);
6543 /* The offset of this dimension. offset = offset - lbound * stride. */
6544 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6545 lbound, stride);
6546 offset = fold_build2_loc (input_location, MINUS_EXPR,
6547 gfc_array_index_type, offset, tmp);
6549 /* The size of this dimension, and the stride of the next. */
6550 if (n + 1 < as->rank)
6552 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
6554 if (no_repack || partial != NULL_TREE)
6555 stmt_unpacked =
6556 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
6558 /* Figure out the stride if not a known constant. */
6559 if (!INTEGER_CST_P (stride))
6561 if (no_repack)
6562 stmt_packed = NULL_TREE;
6563 else
6565 /* Calculate stride = size * (ubound + 1 - lbound). */
6566 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6567 gfc_array_index_type,
6568 gfc_index_one_node, lbound);
6569 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6570 gfc_array_index_type, ubound, tmp);
6571 size = fold_build2_loc (input_location, MULT_EXPR,
6572 gfc_array_index_type, size, tmp);
6573 stmt_packed = size;
6576 /* Assign the stride. */
6577 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6578 tmp = fold_build3_loc (input_location, COND_EXPR,
6579 gfc_array_index_type, partial,
6580 stmt_unpacked, stmt_packed);
6581 else
6582 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
6583 gfc_add_modify (&init, stride, tmp);
6586 else
6588 stride = GFC_TYPE_ARRAY_SIZE (type);
6590 if (stride && !INTEGER_CST_P (stride))
6592 /* Calculate size = stride * (ubound + 1 - lbound). */
6593 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6594 gfc_array_index_type,
6595 gfc_index_one_node, lbound);
6596 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6597 gfc_array_index_type,
6598 ubound, tmp);
6599 tmp = fold_build2_loc (input_location, MULT_EXPR,
6600 gfc_array_index_type,
6601 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
6602 gfc_add_modify (&init, stride, tmp);
6607 gfc_trans_array_cobounds (type, &init, sym);
6609 /* Set the offset. */
6610 if (VAR_P (GFC_TYPE_ARRAY_OFFSET (type)))
6611 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6613 gfc_trans_vla_type_sizes (sym, &init);
6615 stmtInit = gfc_finish_block (&init);
6617 /* Only do the entry/initialization code if the arg is present. */
6618 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6619 optional_arg = (sym->attr.optional
6620 || (sym->ns->proc_name->attr.entry_master
6621 && sym->attr.dummy));
6622 if (optional_arg)
6624 tmp = gfc_conv_expr_present (sym);
6625 stmtInit = build3_v (COND_EXPR, tmp, stmtInit,
6626 build_empty_stmt (input_location));
6629 /* Cleanup code. */
6630 if (no_repack)
6631 stmtCleanup = NULL_TREE;
6632 else
6634 stmtblock_t cleanup;
6635 gfc_start_block (&cleanup);
6637 if (sym->attr.intent != INTENT_IN)
6639 /* Copy the data back. */
6640 tmp = build_call_expr_loc (input_location,
6641 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
6642 gfc_add_expr_to_block (&cleanup, tmp);
6645 /* Free the temporary. */
6646 tmp = gfc_call_free (tmpdesc);
6647 gfc_add_expr_to_block (&cleanup, tmp);
6649 stmtCleanup = gfc_finish_block (&cleanup);
6651 /* Only do the cleanup if the array was repacked. */
6652 if (is_classarray)
6653 /* For a class array the dummy array descriptor is in the _class
6654 component. */
6655 tmp = gfc_class_data_get (dumdesc);
6656 else
6657 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
6658 tmp = gfc_conv_descriptor_data_get (tmp);
6659 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6660 tmp, tmpdesc);
6661 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6662 build_empty_stmt (input_location));
6664 if (optional_arg)
6666 tmp = gfc_conv_expr_present (sym);
6667 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6668 build_empty_stmt (input_location));
6672 /* We don't need to free any memory allocated by internal_pack as it will
6673 be freed at the end of the function by pop_context. */
6674 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
6676 gfc_restore_backend_locus (&loc);
6680 /* Calculate the overall offset, including subreferences. */
6681 static void
6682 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
6683 bool subref, gfc_expr *expr)
6685 tree tmp;
6686 tree field;
6687 tree stride;
6688 tree index;
6689 gfc_ref *ref;
6690 gfc_se start;
6691 int n;
6693 /* If offset is NULL and this is not a subreferenced array, there is
6694 nothing to do. */
6695 if (offset == NULL_TREE)
6697 if (subref)
6698 offset = gfc_index_zero_node;
6699 else
6700 return;
6703 tmp = build_array_ref (desc, offset, NULL, NULL);
6705 /* Offset the data pointer for pointer assignments from arrays with
6706 subreferences; e.g. my_integer => my_type(:)%integer_component. */
6707 if (subref)
6709 /* Go past the array reference. */
6710 for (ref = expr->ref; ref; ref = ref->next)
6711 if (ref->type == REF_ARRAY &&
6712 ref->u.ar.type != AR_ELEMENT)
6714 ref = ref->next;
6715 break;
6718 /* Calculate the offset for each subsequent subreference. */
6719 for (; ref; ref = ref->next)
6721 switch (ref->type)
6723 case REF_COMPONENT:
6724 field = ref->u.c.component->backend_decl;
6725 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6726 tmp = fold_build3_loc (input_location, COMPONENT_REF,
6727 TREE_TYPE (field),
6728 tmp, field, NULL_TREE);
6729 break;
6731 case REF_SUBSTRING:
6732 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
6733 gfc_init_se (&start, NULL);
6734 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
6735 gfc_add_block_to_block (block, &start.pre);
6736 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
6737 break;
6739 case REF_ARRAY:
6740 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
6741 && ref->u.ar.type == AR_ELEMENT);
6743 /* TODO - Add bounds checking. */
6744 stride = gfc_index_one_node;
6745 index = gfc_index_zero_node;
6746 for (n = 0; n < ref->u.ar.dimen; n++)
6748 tree itmp;
6749 tree jtmp;
6751 /* Update the index. */
6752 gfc_init_se (&start, NULL);
6753 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
6754 itmp = gfc_evaluate_now (start.expr, block);
6755 gfc_init_se (&start, NULL);
6756 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
6757 jtmp = gfc_evaluate_now (start.expr, block);
6758 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6759 gfc_array_index_type, itmp, jtmp);
6760 itmp = fold_build2_loc (input_location, MULT_EXPR,
6761 gfc_array_index_type, itmp, stride);
6762 index = fold_build2_loc (input_location, PLUS_EXPR,
6763 gfc_array_index_type, itmp, index);
6764 index = gfc_evaluate_now (index, block);
6766 /* Update the stride. */
6767 gfc_init_se (&start, NULL);
6768 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
6769 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6770 gfc_array_index_type, start.expr,
6771 jtmp);
6772 itmp = fold_build2_loc (input_location, PLUS_EXPR,
6773 gfc_array_index_type,
6774 gfc_index_one_node, itmp);
6775 stride = fold_build2_loc (input_location, MULT_EXPR,
6776 gfc_array_index_type, stride, itmp);
6777 stride = gfc_evaluate_now (stride, block);
6780 /* Apply the index to obtain the array element. */
6781 tmp = gfc_build_array_ref (tmp, index, NULL);
6782 break;
6784 default:
6785 gcc_unreachable ();
6786 break;
6791 /* Set the target data pointer. */
6792 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
6793 gfc_conv_descriptor_data_set (block, parm, offset);
6797 /* gfc_conv_expr_descriptor needs the string length an expression
6798 so that the size of the temporary can be obtained. This is done
6799 by adding up the string lengths of all the elements in the
6800 expression. Function with non-constant expressions have their
6801 string lengths mapped onto the actual arguments using the
6802 interface mapping machinery in trans-expr.c. */
6803 static void
6804 get_array_charlen (gfc_expr *expr, gfc_se *se)
6806 gfc_interface_mapping mapping;
6807 gfc_formal_arglist *formal;
6808 gfc_actual_arglist *arg;
6809 gfc_se tse;
6811 if (expr->ts.u.cl->length
6812 && gfc_is_constant_expr (expr->ts.u.cl->length))
6814 if (!expr->ts.u.cl->backend_decl)
6815 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6816 return;
6819 switch (expr->expr_type)
6821 case EXPR_OP:
6822 get_array_charlen (expr->value.op.op1, se);
6824 /* For parentheses the expression ts.u.cl is identical. */
6825 if (expr->value.op.op == INTRINSIC_PARENTHESES)
6826 return;
6828 expr->ts.u.cl->backend_decl =
6829 gfc_create_var (gfc_charlen_type_node, "sln");
6831 if (expr->value.op.op2)
6833 get_array_charlen (expr->value.op.op2, se);
6835 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
6837 /* Add the string lengths and assign them to the expression
6838 string length backend declaration. */
6839 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6840 fold_build2_loc (input_location, PLUS_EXPR,
6841 gfc_charlen_type_node,
6842 expr->value.op.op1->ts.u.cl->backend_decl,
6843 expr->value.op.op2->ts.u.cl->backend_decl));
6845 else
6846 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6847 expr->value.op.op1->ts.u.cl->backend_decl);
6848 break;
6850 case EXPR_FUNCTION:
6851 if (expr->value.function.esym == NULL
6852 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
6854 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6855 break;
6858 /* Map expressions involving the dummy arguments onto the actual
6859 argument expressions. */
6860 gfc_init_interface_mapping (&mapping);
6861 formal = gfc_sym_get_dummy_args (expr->symtree->n.sym);
6862 arg = expr->value.function.actual;
6864 /* Set se = NULL in the calls to the interface mapping, to suppress any
6865 backend stuff. */
6866 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
6868 if (!arg->expr)
6869 continue;
6870 if (formal->sym)
6871 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
6874 gfc_init_se (&tse, NULL);
6876 /* Build the expression for the character length and convert it. */
6877 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
6879 gfc_add_block_to_block (&se->pre, &tse.pre);
6880 gfc_add_block_to_block (&se->post, &tse.post);
6881 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
6882 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
6883 TREE_TYPE (tse.expr), tse.expr,
6884 build_zero_cst (TREE_TYPE (tse.expr)));
6885 expr->ts.u.cl->backend_decl = tse.expr;
6886 gfc_free_interface_mapping (&mapping);
6887 break;
6889 default:
6890 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6891 break;
6896 /* Helper function to check dimensions. */
6897 static bool
6898 transposed_dims (gfc_ss *ss)
6900 int n;
6902 for (n = 0; n < ss->dimen; n++)
6903 if (ss->dim[n] != n)
6904 return true;
6905 return false;
6909 /* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
6910 AR_FULL, suitable for the scalarizer. */
6912 static gfc_ss *
6913 walk_coarray (gfc_expr *e)
6915 gfc_ss *ss;
6917 gcc_assert (gfc_get_corank (e) > 0);
6919 ss = gfc_walk_expr (e);
6921 /* Fix scalar coarray. */
6922 if (ss == gfc_ss_terminator)
6924 gfc_ref *ref;
6926 ref = e->ref;
6927 while (ref)
6929 if (ref->type == REF_ARRAY
6930 && ref->u.ar.codimen > 0)
6931 break;
6933 ref = ref->next;
6936 gcc_assert (ref != NULL);
6937 if (ref->u.ar.type == AR_ELEMENT)
6938 ref->u.ar.type = AR_SECTION;
6939 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
6942 return ss;
6946 /* Convert an array for passing as an actual argument. Expressions and
6947 vector subscripts are evaluated and stored in a temporary, which is then
6948 passed. For whole arrays the descriptor is passed. For array sections
6949 a modified copy of the descriptor is passed, but using the original data.
6951 This function is also used for array pointer assignments, and there
6952 are three cases:
6954 - se->want_pointer && !se->direct_byref
6955 EXPR is an actual argument. On exit, se->expr contains a
6956 pointer to the array descriptor.
6958 - !se->want_pointer && !se->direct_byref
6959 EXPR is an actual argument to an intrinsic function or the
6960 left-hand side of a pointer assignment. On exit, se->expr
6961 contains the descriptor for EXPR.
6963 - !se->want_pointer && se->direct_byref
6964 EXPR is the right-hand side of a pointer assignment and
6965 se->expr is the descriptor for the previously-evaluated
6966 left-hand side. The function creates an assignment from
6967 EXPR to se->expr.
6970 The se->force_tmp flag disables the non-copying descriptor optimization
6971 that is used for transpose. It may be used in cases where there is an
6972 alias between the transpose argument and another argument in the same
6973 function call. */
6975 void
6976 gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
6978 gfc_ss *ss;
6979 gfc_ss_type ss_type;
6980 gfc_ss_info *ss_info;
6981 gfc_loopinfo loop;
6982 gfc_array_info *info;
6983 int need_tmp;
6984 int n;
6985 tree tmp;
6986 tree desc;
6987 stmtblock_t block;
6988 tree start;
6989 tree offset;
6990 int full;
6991 bool subref_array_target = false;
6992 gfc_expr *arg, *ss_expr;
6994 if (se->want_coarray)
6995 ss = walk_coarray (expr);
6996 else
6997 ss = gfc_walk_expr (expr);
6999 gcc_assert (ss != NULL);
7000 gcc_assert (ss != gfc_ss_terminator);
7002 ss_info = ss->info;
7003 ss_type = ss_info->type;
7004 ss_expr = ss_info->expr;
7006 /* Special case: TRANSPOSE which needs no temporary. */
7007 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
7008 && (arg = gfc_get_noncopying_intrinsic_argument (expr)) != NULL)
7010 /* This is a call to transpose which has already been handled by the
7011 scalarizer, so that we just need to get its argument's descriptor. */
7012 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
7013 expr = expr->value.function.actual->expr;
7016 /* Special case things we know we can pass easily. */
7017 switch (expr->expr_type)
7019 case EXPR_VARIABLE:
7020 /* If we have a linear array section, we can pass it directly.
7021 Otherwise we need to copy it into a temporary. */
7023 gcc_assert (ss_type == GFC_SS_SECTION);
7024 gcc_assert (ss_expr == expr);
7025 info = &ss_info->data.array;
7027 /* Get the descriptor for the array. */
7028 gfc_conv_ss_descriptor (&se->pre, ss, 0);
7029 desc = info->descriptor;
7031 subref_array_target = se->direct_byref && is_subref_array (expr);
7032 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
7033 && !subref_array_target;
7035 if (se->force_tmp)
7036 need_tmp = 1;
7038 if (need_tmp)
7039 full = 0;
7040 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7042 /* Create a new descriptor if the array doesn't have one. */
7043 full = 0;
7045 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
7046 full = 1;
7047 else if (se->direct_byref)
7048 full = 0;
7049 else
7050 full = gfc_full_array_ref_p (info->ref, NULL);
7052 if (full && !transposed_dims (ss))
7054 if (se->direct_byref && !se->byref_noassign)
7056 /* Copy the descriptor for pointer assignments. */
7057 gfc_add_modify (&se->pre, se->expr, desc);
7059 /* Add any offsets from subreferences. */
7060 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
7061 subref_array_target, expr);
7063 /* ....and set the span field. */
7064 tmp = gfc_get_array_span (desc, expr);
7065 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7067 else if (se->want_pointer)
7069 /* We pass full arrays directly. This means that pointers and
7070 allocatable arrays should also work. */
7071 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7073 else
7075 se->expr = desc;
7078 if (expr->ts.type == BT_CHARACTER)
7079 se->string_length = gfc_get_expr_charlen (expr);
7081 gfc_free_ss_chain (ss);
7082 return;
7084 break;
7086 case EXPR_FUNCTION:
7087 /* A transformational function return value will be a temporary
7088 array descriptor. We still need to go through the scalarizer
7089 to create the descriptor. Elemental functions are handled as
7090 arbitrary expressions, i.e. copy to a temporary. */
7092 if (se->direct_byref)
7094 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
7096 /* For pointer assignments pass the descriptor directly. */
7097 if (se->ss == NULL)
7098 se->ss = ss;
7099 else
7100 gcc_assert (se->ss == ss);
7102 if (!is_pointer_array (se->expr))
7104 tmp = gfc_get_element_type (TREE_TYPE (se->expr));
7105 tmp = fold_convert (gfc_array_index_type,
7106 size_in_bytes (tmp));
7107 gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
7110 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7111 gfc_conv_expr (se, expr);
7113 gfc_free_ss_chain (ss);
7114 return;
7117 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
7119 if (ss_expr != expr)
7120 /* Elemental function. */
7121 gcc_assert ((expr->value.function.esym != NULL
7122 && expr->value.function.esym->attr.elemental)
7123 || (expr->value.function.isym != NULL
7124 && expr->value.function.isym->elemental)
7125 || gfc_inline_intrinsic_function_p (expr));
7126 else
7127 gcc_assert (ss_type == GFC_SS_INTRINSIC);
7129 need_tmp = 1;
7130 if (expr->ts.type == BT_CHARACTER
7131 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
7132 get_array_charlen (expr, se);
7134 info = NULL;
7136 else
7138 /* Transformational function. */
7139 info = &ss_info->data.array;
7140 need_tmp = 0;
7142 break;
7144 case EXPR_ARRAY:
7145 /* Constant array constructors don't need a temporary. */
7146 if (ss_type == GFC_SS_CONSTRUCTOR
7147 && expr->ts.type != BT_CHARACTER
7148 && gfc_constant_array_constructor_p (expr->value.constructor))
7150 need_tmp = 0;
7151 info = &ss_info->data.array;
7153 else
7155 need_tmp = 1;
7156 info = NULL;
7158 break;
7160 default:
7161 /* Something complicated. Copy it into a temporary. */
7162 need_tmp = 1;
7163 info = NULL;
7164 break;
7167 /* If we are creating a temporary, we don't need to bother about aliases
7168 anymore. */
7169 if (need_tmp)
7170 se->force_tmp = 0;
7172 gfc_init_loopinfo (&loop);
7174 /* Associate the SS with the loop. */
7175 gfc_add_ss_to_loop (&loop, ss);
7177 /* Tell the scalarizer not to bother creating loop variables, etc. */
7178 if (!need_tmp)
7179 loop.array_parameter = 1;
7180 else
7181 /* The right-hand side of a pointer assignment mustn't use a temporary. */
7182 gcc_assert (!se->direct_byref);
7184 /* Do we need bounds checking or not? */
7185 ss->no_bounds_check = expr->no_bounds_check;
7187 /* Setup the scalarizing loops and bounds. */
7188 gfc_conv_ss_startstride (&loop);
7190 if (need_tmp)
7192 if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
7193 get_array_charlen (expr, se);
7195 /* Tell the scalarizer to make a temporary. */
7196 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
7197 ((expr->ts.type == BT_CHARACTER)
7198 ? expr->ts.u.cl->backend_decl
7199 : NULL),
7200 loop.dimen);
7202 se->string_length = loop.temp_ss->info->string_length;
7203 gcc_assert (loop.temp_ss->dimen == loop.dimen);
7204 gfc_add_ss_to_loop (&loop, loop.temp_ss);
7207 gfc_conv_loop_setup (&loop, & expr->where);
7209 if (need_tmp)
7211 /* Copy into a temporary and pass that. We don't need to copy the data
7212 back because expressions and vector subscripts must be INTENT_IN. */
7213 /* TODO: Optimize passing function return values. */
7214 gfc_se lse;
7215 gfc_se rse;
7216 bool deep_copy;
7218 /* Start the copying loops. */
7219 gfc_mark_ss_chain_used (loop.temp_ss, 1);
7220 gfc_mark_ss_chain_used (ss, 1);
7221 gfc_start_scalarized_body (&loop, &block);
7223 /* Copy each data element. */
7224 gfc_init_se (&lse, NULL);
7225 gfc_copy_loopinfo_to_se (&lse, &loop);
7226 gfc_init_se (&rse, NULL);
7227 gfc_copy_loopinfo_to_se (&rse, &loop);
7229 lse.ss = loop.temp_ss;
7230 rse.ss = ss;
7232 gfc_conv_scalarized_array_ref (&lse, NULL);
7233 if (expr->ts.type == BT_CHARACTER)
7235 gfc_conv_expr (&rse, expr);
7236 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
7237 rse.expr = build_fold_indirect_ref_loc (input_location,
7238 rse.expr);
7240 else
7241 gfc_conv_expr_val (&rse, expr);
7243 gfc_add_block_to_block (&block, &rse.pre);
7244 gfc_add_block_to_block (&block, &lse.pre);
7246 lse.string_length = rse.string_length;
7248 deep_copy = !se->data_not_needed
7249 && (expr->expr_type == EXPR_VARIABLE
7250 || expr->expr_type == EXPR_ARRAY);
7251 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
7252 deep_copy, false);
7253 gfc_add_expr_to_block (&block, tmp);
7255 /* Finish the copying loops. */
7256 gfc_trans_scalarizing_loops (&loop, &block);
7258 desc = loop.temp_ss->info->data.array.descriptor;
7260 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
7262 desc = info->descriptor;
7263 se->string_length = ss_info->string_length;
7265 else
7267 /* We pass sections without copying to a temporary. Make a new
7268 descriptor and point it at the section we want. The loop variable
7269 limits will be the limits of the section.
7270 A function may decide to repack the array to speed up access, but
7271 we're not bothered about that here. */
7272 int dim, ndim, codim;
7273 tree parm;
7274 tree parmtype;
7275 tree stride;
7276 tree from;
7277 tree to;
7278 tree base;
7279 bool onebased = false, rank_remap;
7281 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
7282 rank_remap = ss->dimen < ndim;
7284 if (se->want_coarray)
7286 gfc_array_ref *ar = &info->ref->u.ar;
7288 codim = gfc_get_corank (expr);
7289 for (n = 0; n < codim - 1; n++)
7291 /* Make sure we are not lost somehow. */
7292 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
7294 /* Make sure the call to gfc_conv_section_startstride won't
7295 generate unnecessary code to calculate stride. */
7296 gcc_assert (ar->stride[n + ndim] == NULL);
7298 gfc_conv_section_startstride (&loop.pre, ss, n + ndim);
7299 loop.from[n + loop.dimen] = info->start[n + ndim];
7300 loop.to[n + loop.dimen] = info->end[n + ndim];
7303 gcc_assert (n == codim - 1);
7304 evaluate_bound (&loop.pre, info->start, ar->start,
7305 info->descriptor, n + ndim, true,
7306 ar->as->type == AS_DEFERRED);
7307 loop.from[n + loop.dimen] = info->start[n + ndim];
7309 else
7310 codim = 0;
7312 /* Set the string_length for a character array. */
7313 if (expr->ts.type == BT_CHARACTER)
7314 se->string_length = gfc_get_expr_charlen (expr);
7316 /* If we have an array section or are assigning make sure that
7317 the lower bound is 1. References to the full
7318 array should otherwise keep the original bounds. */
7319 if ((!info->ref || info->ref->u.ar.type != AR_FULL) && !se->want_pointer)
7320 for (dim = 0; dim < loop.dimen; dim++)
7321 if (!integer_onep (loop.from[dim]))
7323 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7324 gfc_array_index_type, gfc_index_one_node,
7325 loop.from[dim]);
7326 loop.to[dim] = fold_build2_loc (input_location, PLUS_EXPR,
7327 gfc_array_index_type,
7328 loop.to[dim], tmp);
7329 loop.from[dim] = gfc_index_one_node;
7332 desc = info->descriptor;
7333 if (se->direct_byref && !se->byref_noassign)
7335 /* For pointer assignments we fill in the destination.... */
7336 parm = se->expr;
7337 parmtype = TREE_TYPE (parm);
7339 /* ....and set the span field. */
7340 tmp = gfc_get_array_span (desc, expr);
7341 gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);
7343 else
7345 /* Otherwise make a new one. */
7346 if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
7347 parmtype = gfc_typenode_for_spec (&expr->ts);
7348 else
7349 parmtype = gfc_get_element_type (TREE_TYPE (desc));
7351 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
7352 loop.from, loop.to, 0,
7353 GFC_ARRAY_UNKNOWN, false);
7354 parm = gfc_create_var (parmtype, "parm");
7356 /* When expression is a class object, then add the class' handle to
7357 the parm_decl. */
7358 if (expr->ts.type == BT_CLASS && expr->expr_type == EXPR_VARIABLE)
7360 gfc_expr *class_expr = gfc_find_and_cut_at_last_class_ref (expr);
7361 gfc_se classse;
7363 /* class_expr can be NULL, when no _class ref is in expr.
7364 We must not fix this here with a gfc_fix_class_ref (). */
7365 if (class_expr)
7367 gfc_init_se (&classse, NULL);
7368 gfc_conv_expr (&classse, class_expr);
7369 gfc_free_expr (class_expr);
7371 gcc_assert (classse.pre.head == NULL_TREE
7372 && classse.post.head == NULL_TREE);
7373 gfc_allocate_lang_decl (parm);
7374 GFC_DECL_SAVED_DESCRIPTOR (parm) = classse.expr;
7379 offset = gfc_index_zero_node;
7381 /* The following can be somewhat confusing. We have two
7382 descriptors, a new one and the original array.
7383 {parm, parmtype, dim} refer to the new one.
7384 {desc, type, n, loop} refer to the original, which maybe
7385 a descriptorless array.
7386 The bounds of the scalarization are the bounds of the section.
7387 We don't have to worry about numeric overflows when calculating
7388 the offsets because all elements are within the array data. */
7390 /* Set the dtype. */
7391 tmp = gfc_conv_descriptor_dtype (parm);
7392 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
7394 /* Set offset for assignments to pointer only to zero if it is not
7395 the full array. */
7396 if ((se->direct_byref || se->use_offset)
7397 && ((info->ref && info->ref->u.ar.type != AR_FULL)
7398 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
7399 base = gfc_index_zero_node;
7400 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7401 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
7402 else
7403 base = NULL_TREE;
7405 for (n = 0; n < ndim; n++)
7407 stride = gfc_conv_array_stride (desc, n);
7409 /* Work out the offset. */
7410 if (info->ref
7411 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
7413 gcc_assert (info->subscript[n]
7414 && info->subscript[n]->info->type == GFC_SS_SCALAR);
7415 start = info->subscript[n]->info->data.scalar.value;
7417 else
7419 /* Evaluate and remember the start of the section. */
7420 start = info->start[n];
7421 stride = gfc_evaluate_now (stride, &loop.pre);
7424 tmp = gfc_conv_array_lbound (desc, n);
7425 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
7426 start, tmp);
7427 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
7428 tmp, stride);
7429 offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
7430 offset, tmp);
7432 if (info->ref
7433 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
7435 /* For elemental dimensions, we only need the offset. */
7436 continue;
7439 /* Vector subscripts need copying and are handled elsewhere. */
7440 if (info->ref)
7441 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
7443 /* look for the corresponding scalarizer dimension: dim. */
7444 for (dim = 0; dim < ndim; dim++)
7445 if (ss->dim[dim] == n)
7446 break;
7448 /* loop exited early: the DIM being looked for has been found. */
7449 gcc_assert (dim < ndim);
7451 /* Set the new lower bound. */
7452 from = loop.from[dim];
7453 to = loop.to[dim];
7455 onebased = integer_onep (from);
7456 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
7457 gfc_rank_cst[dim], from);
7459 /* Set the new upper bound. */
7460 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
7461 gfc_rank_cst[dim], to);
7463 /* Multiply the stride by the section stride to get the
7464 total stride. */
7465 stride = fold_build2_loc (input_location, MULT_EXPR,
7466 gfc_array_index_type,
7467 stride, info->stride[n]);
7469 if ((se->direct_byref || se->use_offset)
7470 && ((info->ref && info->ref->u.ar.type != AR_FULL)
7471 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
7473 base = fold_build2_loc (input_location, MINUS_EXPR,
7474 TREE_TYPE (base), base, stride);
7476 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)) || se->use_offset)
7478 bool toonebased;
7479 tmp = gfc_conv_array_lbound (desc, n);
7480 toonebased = integer_onep (tmp);
7481 // lb(arr) - from (- start + 1)
7482 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7483 TREE_TYPE (base), tmp, from);
7484 if (onebased && toonebased)
7486 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7487 TREE_TYPE (base), tmp, start);
7488 tmp = fold_build2_loc (input_location, PLUS_EXPR,
7489 TREE_TYPE (base), tmp,
7490 gfc_index_one_node);
7492 tmp = fold_build2_loc (input_location, MULT_EXPR,
7493 TREE_TYPE (base), tmp,
7494 gfc_conv_array_stride (desc, n));
7495 base = fold_build2_loc (input_location, PLUS_EXPR,
7496 TREE_TYPE (base), tmp, base);
7499 /* Store the new stride. */
7500 gfc_conv_descriptor_stride_set (&loop.pre, parm,
7501 gfc_rank_cst[dim], stride);
7504 for (n = loop.dimen; n < loop.dimen + codim; n++)
7506 from = loop.from[n];
7507 to = loop.to[n];
7508 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
7509 gfc_rank_cst[n], from);
7510 if (n < loop.dimen + codim - 1)
7511 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
7512 gfc_rank_cst[n], to);
7515 if (se->data_not_needed)
7516 gfc_conv_descriptor_data_set (&loop.pre, parm,
7517 gfc_index_zero_node);
7518 else
7519 /* Point the data pointer at the 1st element in the section. */
7520 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
7521 subref_array_target, expr);
7523 /* Force the offset to be -1, when the lower bound of the highest
7524 dimension is one and the symbol is present and is not a
7525 pointer/allocatable or associated. */
7526 if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7527 && !se->data_not_needed)
7528 || (se->use_offset && base != NULL_TREE))
7530 /* Set the offset depending on base. */
7531 tmp = rank_remap && !se->direct_byref ?
7532 fold_build2_loc (input_location, PLUS_EXPR,
7533 gfc_array_index_type, base,
7534 offset)
7535 : base;
7536 gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
7538 else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
7539 && !se->data_not_needed
7540 && (!rank_remap || se->use_offset))
7542 gfc_conv_descriptor_offset_set (&loop.pre, parm,
7543 gfc_conv_descriptor_offset_get (desc));
7545 else if (onebased && (!rank_remap || se->use_offset)
7546 && expr->symtree
7547 && !(expr->symtree->n.sym && expr->symtree->n.sym->ts.type == BT_CLASS
7548 && !CLASS_DATA (expr->symtree->n.sym)->attr.class_pointer)
7549 && !expr->symtree->n.sym->attr.allocatable
7550 && !expr->symtree->n.sym->attr.pointer
7551 && !expr->symtree->n.sym->attr.host_assoc
7552 && !expr->symtree->n.sym->attr.use_assoc)
7554 /* Set the offset to -1. */
7555 mpz_t minus_one;
7556 mpz_init_set_si (minus_one, -1);
7557 tmp = gfc_conv_mpz_to_tree (minus_one, gfc_index_integer_kind);
7558 gfc_conv_descriptor_offset_set (&loop.pre, parm, tmp);
7560 else
7562 /* Only the callee knows what the correct offset it, so just set
7563 it to zero here. */
7564 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
7566 desc = parm;
7569 /* For class arrays add the class tree into the saved descriptor to
7570 enable getting of _vptr and the like. */
7571 if (expr->expr_type == EXPR_VARIABLE && VAR_P (desc)
7572 && IS_CLASS_ARRAY (expr->symtree->n.sym))
7574 gfc_allocate_lang_decl (desc);
7575 GFC_DECL_SAVED_DESCRIPTOR (desc) =
7576 DECL_LANG_SPECIFIC (expr->symtree->n.sym->backend_decl) ?
7577 GFC_DECL_SAVED_DESCRIPTOR (expr->symtree->n.sym->backend_decl)
7578 : expr->symtree->n.sym->backend_decl;
7580 else if (expr->expr_type == EXPR_ARRAY && VAR_P (desc)
7581 && IS_CLASS_ARRAY (expr))
7583 tree vtype;
7584 gfc_allocate_lang_decl (desc);
7585 tmp = gfc_create_var (expr->ts.u.derived->backend_decl, "class");
7586 GFC_DECL_SAVED_DESCRIPTOR (desc) = tmp;
7587 vtype = gfc_class_vptr_get (tmp);
7588 gfc_add_modify (&se->pre, vtype,
7589 gfc_build_addr_expr (TREE_TYPE (vtype),
7590 gfc_find_vtab (&expr->ts)->backend_decl));
7592 if (!se->direct_byref || se->byref_noassign)
7594 /* Get a pointer to the new descriptor. */
7595 if (se->want_pointer)
7596 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7597 else
7598 se->expr = desc;
7601 gfc_add_block_to_block (&se->pre, &loop.pre);
7602 gfc_add_block_to_block (&se->post, &loop.post);
7604 /* Cleanup the scalarizer. */
7605 gfc_cleanup_loop (&loop);
7608 /* Helper function for gfc_conv_array_parameter if array size needs to be
7609 computed. */
7611 static void
7612 array_parameter_size (tree desc, gfc_expr *expr, tree *size)
7614 tree elem;
7615 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
7616 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
7617 else if (expr->rank > 1)
7618 *size = build_call_expr_loc (input_location,
7619 gfor_fndecl_size0, 1,
7620 gfc_build_addr_expr (NULL, desc));
7621 else
7623 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
7624 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
7626 *size = fold_build2_loc (input_location, MINUS_EXPR,
7627 gfc_array_index_type, ubound, lbound);
7628 *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7629 *size, gfc_index_one_node);
7630 *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
7631 *size, gfc_index_zero_node);
7633 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
7634 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7635 *size, fold_convert (gfc_array_index_type, elem));
7638 /* Convert an array for passing as an actual parameter. */
7639 /* TODO: Optimize passing g77 arrays. */
7641 void
7642 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
7643 const gfc_symbol *fsym, const char *proc_name,
7644 tree *size)
7646 tree ptr;
7647 tree desc;
7648 tree tmp = NULL_TREE;
7649 tree stmt;
7650 tree parent = DECL_CONTEXT (current_function_decl);
7651 bool full_array_var;
7652 bool this_array_result;
7653 bool contiguous;
7654 bool no_pack;
7655 bool array_constructor;
7656 bool good_allocatable;
7657 bool ultimate_ptr_comp;
7658 bool ultimate_alloc_comp;
7659 gfc_symbol *sym;
7660 stmtblock_t block;
7661 gfc_ref *ref;
7663 ultimate_ptr_comp = false;
7664 ultimate_alloc_comp = false;
7666 for (ref = expr->ref; ref; ref = ref->next)
7668 if (ref->next == NULL)
7669 break;
7671 if (ref->type == REF_COMPONENT)
7673 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
7674 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
7678 full_array_var = false;
7679 contiguous = false;
7681 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
7682 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
7684 sym = full_array_var ? expr->symtree->n.sym : NULL;
7686 /* The symbol should have an array specification. */
7687 gcc_assert (!sym || sym->as || ref->u.ar.as);
7689 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
7691 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
7692 expr->ts.u.cl->backend_decl = tmp;
7693 se->string_length = tmp;
7696 /* Is this the result of the enclosing procedure? */
7697 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
7698 if (this_array_result
7699 && (sym->backend_decl != current_function_decl)
7700 && (sym->backend_decl != parent))
7701 this_array_result = false;
7703 /* Passing address of the array if it is not pointer or assumed-shape. */
7704 if (full_array_var && g77 && !this_array_result
7705 && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
7707 tmp = gfc_get_symbol_decl (sym);
7709 if (sym->ts.type == BT_CHARACTER)
7710 se->string_length = sym->ts.u.cl->backend_decl;
7712 if (!sym->attr.pointer
7713 && sym->as
7714 && sym->as->type != AS_ASSUMED_SHAPE
7715 && sym->as->type != AS_DEFERRED
7716 && sym->as->type != AS_ASSUMED_RANK
7717 && !sym->attr.allocatable)
7719 /* Some variables are declared directly, others are declared as
7720 pointers and allocated on the heap. */
7721 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
7722 se->expr = tmp;
7723 else
7724 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
7725 if (size)
7726 array_parameter_size (tmp, expr, size);
7727 return;
7730 if (sym->attr.allocatable)
7732 if (sym->attr.dummy || sym->attr.result)
7734 gfc_conv_expr_descriptor (se, expr);
7735 tmp = se->expr;
7737 if (size)
7738 array_parameter_size (tmp, expr, size);
7739 se->expr = gfc_conv_array_data (tmp);
7740 return;
7744 /* A convenient reduction in scope. */
7745 contiguous = g77 && !this_array_result && contiguous;
7747 /* There is no need to pack and unpack the array, if it is contiguous
7748 and not a deferred- or assumed-shape array, or if it is simply
7749 contiguous. */
7750 no_pack = ((sym && sym->as
7751 && !sym->attr.pointer
7752 && sym->as->type != AS_DEFERRED
7753 && sym->as->type != AS_ASSUMED_RANK
7754 && sym->as->type != AS_ASSUMED_SHAPE)
7756 (ref && ref->u.ar.as
7757 && ref->u.ar.as->type != AS_DEFERRED
7758 && ref->u.ar.as->type != AS_ASSUMED_RANK
7759 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
7761 gfc_is_simply_contiguous (expr, false, true));
7763 no_pack = contiguous && no_pack;
7765 /* Array constructors are always contiguous and do not need packing. */
7766 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
7768 /* Same is true of contiguous sections from allocatable variables. */
7769 good_allocatable = contiguous
7770 && expr->symtree
7771 && expr->symtree->n.sym->attr.allocatable;
7773 /* Or ultimate allocatable components. */
7774 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
7776 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
7778 gfc_conv_expr_descriptor (se, expr);
7779 /* Deallocate the allocatable components of structures that are
7780 not variable. */
7781 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
7782 && expr->ts.u.derived->attr.alloc_comp
7783 && expr->expr_type != EXPR_VARIABLE)
7785 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se->expr, expr->rank);
7787 /* The components shall be deallocated before their containing entity. */
7788 gfc_prepend_expr_to_block (&se->post, tmp);
7790 if (expr->ts.type == BT_CHARACTER)
7791 se->string_length = expr->ts.u.cl->backend_decl;
7792 if (size)
7793 array_parameter_size (se->expr, expr, size);
7794 se->expr = gfc_conv_array_data (se->expr);
7795 return;
7798 if (this_array_result)
7800 /* Result of the enclosing function. */
7801 gfc_conv_expr_descriptor (se, expr);
7802 if (size)
7803 array_parameter_size (se->expr, expr, size);
7804 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7806 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
7807 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
7808 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
7809 se->expr));
7811 return;
7813 else
7815 /* Every other type of array. */
7816 se->want_pointer = 1;
7817 gfc_conv_expr_descriptor (se, expr);
7819 if (size)
7820 array_parameter_size (build_fold_indirect_ref_loc (input_location,
7821 se->expr),
7822 expr, size);
7825 /* Deallocate the allocatable components of structures that are
7826 not variable, for descriptorless arguments.
7827 Arguments with a descriptor are handled in gfc_conv_procedure_call. */
7828 if (g77 && (expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
7829 && expr->ts.u.derived->attr.alloc_comp
7830 && expr->expr_type != EXPR_VARIABLE)
7832 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
7833 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
7835 /* The components shall be deallocated before their containing entity. */
7836 gfc_prepend_expr_to_block (&se->post, tmp);
7839 if (g77 || (fsym && fsym->attr.contiguous
7840 && !gfc_is_simply_contiguous (expr, false, true)))
7842 tree origptr = NULL_TREE;
7844 desc = se->expr;
7846 /* For contiguous arrays, save the original value of the descriptor. */
7847 if (!g77)
7849 origptr = gfc_create_var (pvoid_type_node, "origptr");
7850 tmp = build_fold_indirect_ref_loc (input_location, desc);
7851 tmp = gfc_conv_array_data (tmp);
7852 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7853 TREE_TYPE (origptr), origptr,
7854 fold_convert (TREE_TYPE (origptr), tmp));
7855 gfc_add_expr_to_block (&se->pre, tmp);
7858 /* Repack the array. */
7859 if (warn_array_temporaries)
7861 if (fsym)
7862 gfc_warning (OPT_Warray_temporaries,
7863 "Creating array temporary at %L for argument %qs",
7864 &expr->where, fsym->name);
7865 else
7866 gfc_warning (OPT_Warray_temporaries,
7867 "Creating array temporary at %L", &expr->where);
7870 ptr = build_call_expr_loc (input_location,
7871 gfor_fndecl_in_pack, 1, desc);
7873 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7875 tmp = gfc_conv_expr_present (sym);
7876 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
7877 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
7878 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
7881 ptr = gfc_evaluate_now (ptr, &se->pre);
7883 /* Use the packed data for the actual argument, except for contiguous arrays,
7884 where the descriptor's data component is set. */
7885 if (g77)
7886 se->expr = ptr;
7887 else
7889 tmp = build_fold_indirect_ref_loc (input_location, desc);
7891 gfc_ss * ss = gfc_walk_expr (expr);
7892 if (!transposed_dims (ss))
7893 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
7894 else
7896 tree old_field, new_field;
7898 /* The original descriptor has transposed dims so we can't reuse
7899 it directly; we have to create a new one. */
7900 tree old_desc = tmp;
7901 tree new_desc = gfc_create_var (TREE_TYPE (old_desc), "arg_desc");
7903 old_field = gfc_conv_descriptor_dtype (old_desc);
7904 new_field = gfc_conv_descriptor_dtype (new_desc);
7905 gfc_add_modify (&se->pre, new_field, old_field);
7907 old_field = gfc_conv_descriptor_offset (old_desc);
7908 new_field = gfc_conv_descriptor_offset (new_desc);
7909 gfc_add_modify (&se->pre, new_field, old_field);
7911 for (int i = 0; i < expr->rank; i++)
7913 old_field = gfc_conv_descriptor_dimension (old_desc,
7914 gfc_rank_cst[get_array_ref_dim_for_loop_dim (ss, i)]);
7915 new_field = gfc_conv_descriptor_dimension (new_desc,
7916 gfc_rank_cst[i]);
7917 gfc_add_modify (&se->pre, new_field, old_field);
7920 if (flag_coarray == GFC_FCOARRAY_LIB
7921 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (old_desc))
7922 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (old_desc))
7923 == GFC_ARRAY_ALLOCATABLE)
7925 old_field = gfc_conv_descriptor_token (old_desc);
7926 new_field = gfc_conv_descriptor_token (new_desc);
7927 gfc_add_modify (&se->pre, new_field, old_field);
7930 gfc_conv_descriptor_data_set (&se->pre, new_desc, ptr);
7931 se->expr = gfc_build_addr_expr (NULL_TREE, new_desc);
7933 gfc_free_ss (ss);
7936 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
7938 char * msg;
7940 if (fsym && proc_name)
7941 msg = xasprintf ("An array temporary was created for argument "
7942 "'%s' of procedure '%s'", fsym->name, proc_name);
7943 else
7944 msg = xasprintf ("An array temporary was created");
7946 tmp = build_fold_indirect_ref_loc (input_location,
7947 desc);
7948 tmp = gfc_conv_array_data (tmp);
7949 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7950 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7952 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7953 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7954 logical_type_node,
7955 gfc_conv_expr_present (sym), tmp);
7957 gfc_trans_runtime_check (false, true, tmp, &se->pre,
7958 &expr->where, msg);
7959 free (msg);
7962 gfc_start_block (&block);
7964 /* Copy the data back. */
7965 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
7967 tmp = build_call_expr_loc (input_location,
7968 gfor_fndecl_in_unpack, 2, desc, ptr);
7969 gfc_add_expr_to_block (&block, tmp);
7972 /* Free the temporary. */
7973 tmp = gfc_call_free (ptr);
7974 gfc_add_expr_to_block (&block, tmp);
7976 stmt = gfc_finish_block (&block);
7978 gfc_init_block (&block);
7979 /* Only if it was repacked. This code needs to be executed before the
7980 loop cleanup code. */
7981 tmp = build_fold_indirect_ref_loc (input_location,
7982 desc);
7983 tmp = gfc_conv_array_data (tmp);
7984 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
7985 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7987 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7988 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7989 logical_type_node,
7990 gfc_conv_expr_present (sym), tmp);
7992 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
7994 gfc_add_expr_to_block (&block, tmp);
7995 gfc_add_block_to_block (&block, &se->post);
7997 gfc_init_block (&se->post);
7999 /* Reset the descriptor pointer. */
8000 if (!g77)
8002 tmp = build_fold_indirect_ref_loc (input_location, desc);
8003 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
8006 gfc_add_block_to_block (&se->post, &block);
8011 /* This helper function calculates the size in words of a full array. */
8013 tree
8014 gfc_full_array_size (stmtblock_t *block, tree decl, int rank)
8016 tree idx;
8017 tree nelems;
8018 tree tmp;
8019 idx = gfc_rank_cst[rank - 1];
8020 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
8021 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
8022 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
8023 nelems, tmp);
8024 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
8025 tmp, gfc_index_one_node);
8026 tmp = gfc_evaluate_now (tmp, block);
8028 nelems = gfc_conv_descriptor_stride_get (decl, idx);
8029 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8030 nelems, tmp);
8031 return gfc_evaluate_now (tmp, block);
8035 /* Allocate dest to the same size as src, and copy src -> dest.
8036 If no_malloc is set, only the copy is done. */
8038 static tree
8039 duplicate_allocatable (tree dest, tree src, tree type, int rank,
8040 bool no_malloc, bool no_memcpy, tree str_sz,
8041 tree add_when_allocated)
8043 tree tmp;
8044 tree size;
8045 tree nelems;
8046 tree null_cond;
8047 tree null_data;
8048 stmtblock_t block;
8050 /* If the source is null, set the destination to null. Then,
8051 allocate memory to the destination. */
8052 gfc_init_block (&block);
8054 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8056 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
8057 null_data = gfc_finish_block (&block);
8059 gfc_init_block (&block);
8060 if (str_sz != NULL_TREE)
8061 size = str_sz;
8062 else
8063 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8065 if (!no_malloc)
8067 tmp = gfc_call_malloc (&block, type, size);
8068 gfc_add_modify (&block, dest, fold_convert (type, tmp));
8071 if (!no_memcpy)
8073 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8074 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8075 fold_convert (size_type_node, size));
8076 gfc_add_expr_to_block (&block, tmp);
8079 else
8081 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8082 null_data = gfc_finish_block (&block);
8084 gfc_init_block (&block);
8085 if (rank)
8086 nelems = gfc_full_array_size (&block, src, rank);
8087 else
8088 nelems = gfc_index_one_node;
8090 if (str_sz != NULL_TREE)
8091 tmp = fold_convert (gfc_array_index_type, str_sz);
8092 else
8093 tmp = fold_convert (gfc_array_index_type,
8094 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
8095 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
8096 nelems, tmp);
8097 if (!no_malloc)
8099 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
8100 tmp = gfc_call_malloc (&block, tmp, size);
8101 gfc_conv_descriptor_data_set (&block, dest, tmp);
8104 /* We know the temporary and the value will be the same length,
8105 so can use memcpy. */
8106 if (!no_memcpy)
8108 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8109 tmp = build_call_expr_loc (input_location, tmp, 3,
8110 gfc_conv_descriptor_data_get (dest),
8111 gfc_conv_descriptor_data_get (src),
8112 fold_convert (size_type_node, size));
8113 gfc_add_expr_to_block (&block, tmp);
8117 gfc_add_expr_to_block (&block, add_when_allocated);
8118 tmp = gfc_finish_block (&block);
8120 /* Null the destination if the source is null; otherwise do
8121 the allocate and copy. */
8122 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
8123 null_cond = src;
8124 else
8125 null_cond = gfc_conv_descriptor_data_get (src);
8127 null_cond = convert (pvoid_type_node, null_cond);
8128 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8129 null_cond, null_pointer_node);
8130 return build3_v (COND_EXPR, null_cond, tmp, null_data);
8134 /* Allocate dest to the same size as src, and copy data src -> dest. */
8136 tree
8137 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank,
8138 tree add_when_allocated)
8140 return duplicate_allocatable (dest, src, type, rank, false, false,
8141 NULL_TREE, add_when_allocated);
8145 /* Copy data src -> dest. */
8147 tree
8148 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
8150 return duplicate_allocatable (dest, src, type, rank, true, false,
8151 NULL_TREE, NULL_TREE);
8154 /* Allocate dest to the same size as src, but don't copy anything. */
8156 tree
8157 gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
8159 return duplicate_allocatable (dest, src, type, rank, false, true,
8160 NULL_TREE, NULL_TREE);
8164 static tree
8165 duplicate_allocatable_coarray (tree dest, tree dest_tok, tree src,
8166 tree type, int rank)
8168 tree tmp;
8169 tree size;
8170 tree nelems;
8171 tree null_cond;
8172 tree null_data;
8173 stmtblock_t block, globalblock;
8175 /* If the source is null, set the destination to null. Then,
8176 allocate memory to the destination. */
8177 gfc_init_block (&block);
8178 gfc_init_block (&globalblock);
8180 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8182 gfc_se se;
8183 symbol_attribute attr;
8184 tree dummy_desc;
8186 gfc_init_se (&se, NULL);
8187 gfc_clear_attr (&attr);
8188 attr.allocatable = 1;
8189 dummy_desc = gfc_conv_scalar_to_descriptor (&se, dest, attr);
8190 gfc_add_block_to_block (&globalblock, &se.pre);
8191 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
8193 gfc_add_modify (&block, dest, fold_convert (type, null_pointer_node));
8194 gfc_allocate_using_caf_lib (&block, dummy_desc, size,
8195 gfc_build_addr_expr (NULL_TREE, dest_tok),
8196 NULL_TREE, NULL_TREE, NULL_TREE,
8197 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8198 null_data = gfc_finish_block (&block);
8200 gfc_init_block (&block);
8202 gfc_allocate_using_caf_lib (&block, dummy_desc,
8203 fold_convert (size_type_node, size),
8204 gfc_build_addr_expr (NULL_TREE, dest_tok),
8205 NULL_TREE, NULL_TREE, NULL_TREE,
8206 GFC_CAF_COARRAY_ALLOC);
8208 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8209 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
8210 fold_convert (size_type_node, size));
8211 gfc_add_expr_to_block (&block, tmp);
8213 else
8215 /* Set the rank or unitialized memory access may be reported. */
8216 tmp = gfc_conv_descriptor_rank (dest);
8217 gfc_add_modify (&globalblock, tmp, build_int_cst (TREE_TYPE (tmp), rank));
8219 if (rank)
8220 nelems = gfc_full_array_size (&block, src, rank);
8221 else
8222 nelems = integer_one_node;
8224 tmp = fold_convert (size_type_node,
8225 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
8226 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
8227 fold_convert (size_type_node, nelems), tmp);
8229 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
8230 gfc_allocate_using_caf_lib (&block, dest, fold_convert (size_type_node,
8231 size),
8232 gfc_build_addr_expr (NULL_TREE, dest_tok),
8233 NULL_TREE, NULL_TREE, NULL_TREE,
8234 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8235 null_data = gfc_finish_block (&block);
8237 gfc_init_block (&block);
8238 gfc_allocate_using_caf_lib (&block, dest,
8239 fold_convert (size_type_node, size),
8240 gfc_build_addr_expr (NULL_TREE, dest_tok),
8241 NULL_TREE, NULL_TREE, NULL_TREE,
8242 GFC_CAF_COARRAY_ALLOC);
8244 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
8245 tmp = build_call_expr_loc (input_location, tmp, 3,
8246 gfc_conv_descriptor_data_get (dest),
8247 gfc_conv_descriptor_data_get (src),
8248 fold_convert (size_type_node, size));
8249 gfc_add_expr_to_block (&block, tmp);
8252 tmp = gfc_finish_block (&block);
8254 /* Null the destination if the source is null; otherwise do
8255 the register and copy. */
8256 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
8257 null_cond = src;
8258 else
8259 null_cond = gfc_conv_descriptor_data_get (src);
8261 null_cond = convert (pvoid_type_node, null_cond);
8262 null_cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
8263 null_cond, null_pointer_node);
8264 gfc_add_expr_to_block (&globalblock, build3_v (COND_EXPR, null_cond, tmp,
8265 null_data));
8266 return gfc_finish_block (&globalblock);
8270 /* Helper function to abstract whether coarray processing is enabled. */
8272 static bool
8273 caf_enabled (int caf_mode)
8275 return (caf_mode & GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY)
8276 == GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY;
8280 /* Helper function to abstract whether coarray processing is enabled
8281 and we are in a derived type coarray. */
8283 static bool
8284 caf_in_coarray (int caf_mode)
8286 static const int pat = GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY
8287 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY;
8288 return (caf_mode & pat) == pat;
8292 /* Helper function to abstract whether coarray is to deallocate only. */
8294 bool
8295 gfc_caf_is_dealloc_only (int caf_mode)
8297 return (caf_mode & GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY)
8298 == GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY;
8302 /* Recursively traverse an object of derived type, generating code to
8303 deallocate, nullify or copy allocatable components. This is the work horse
8304 function for the functions named in this enum. */
8306 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP,
8307 COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP, REASSIGN_CAF_COMP,
8308 ALLOCATE_PDT_COMP, DEALLOCATE_PDT_COMP, CHECK_PDT_DUMMY};
8310 static gfc_actual_arglist *pdt_param_list;
8312 static tree
8313 structure_alloc_comps (gfc_symbol * der_type, tree decl,
8314 tree dest, int rank, int purpose, int caf_mode)
8316 gfc_component *c;
8317 gfc_loopinfo loop;
8318 stmtblock_t fnblock;
8319 stmtblock_t loopbody;
8320 stmtblock_t tmpblock;
8321 tree decl_type;
8322 tree tmp;
8323 tree comp;
8324 tree dcmp;
8325 tree nelems;
8326 tree index;
8327 tree var;
8328 tree cdecl;
8329 tree ctype;
8330 tree vref, dref;
8331 tree null_cond = NULL_TREE;
8332 tree add_when_allocated;
8333 tree dealloc_fndecl;
8334 tree caf_token;
8335 gfc_symbol *vtab;
8336 int caf_dereg_mode;
8337 symbol_attribute *attr;
8338 bool deallocate_called;
8340 gfc_init_block (&fnblock);
8342 decl_type = TREE_TYPE (decl);
8344 if ((POINTER_TYPE_P (decl_type))
8345 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
8347 decl = build_fold_indirect_ref_loc (input_location, decl);
8348 /* Deref dest in sync with decl, but only when it is not NULL. */
8349 if (dest)
8350 dest = build_fold_indirect_ref_loc (input_location, dest);
8352 /* Update the decl_type because it got dereferenced. */
8353 decl_type = TREE_TYPE (decl);
8356 /* If this is an array of derived types with allocatable components
8357 build a loop and recursively call this function. */
8358 if (TREE_CODE (decl_type) == ARRAY_TYPE
8359 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
8361 tmp = gfc_conv_array_data (decl);
8362 var = build_fold_indirect_ref_loc (input_location, tmp);
8364 /* Get the number of elements - 1 and set the counter. */
8365 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
8367 /* Use the descriptor for an allocatable array. Since this
8368 is a full array reference, we only need the descriptor
8369 information from dimension = rank. */
8370 tmp = gfc_full_array_size (&fnblock, decl, rank);
8371 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8372 gfc_array_index_type, tmp,
8373 gfc_index_one_node);
8375 null_cond = gfc_conv_descriptor_data_get (decl);
8376 null_cond = fold_build2_loc (input_location, NE_EXPR,
8377 logical_type_node, null_cond,
8378 build_int_cst (TREE_TYPE (null_cond), 0));
8380 else
8382 /* Otherwise use the TYPE_DOMAIN information. */
8383 tmp = array_type_nelts (decl_type);
8384 tmp = fold_convert (gfc_array_index_type, tmp);
8387 /* Remember that this is, in fact, the no. of elements - 1. */
8388 nelems = gfc_evaluate_now (tmp, &fnblock);
8389 index = gfc_create_var (gfc_array_index_type, "S");
8391 /* Build the body of the loop. */
8392 gfc_init_block (&loopbody);
8394 vref = gfc_build_array_ref (var, index, NULL);
8396 if ((purpose == COPY_ALLOC_COMP || purpose == COPY_ONLY_ALLOC_COMP)
8397 && !caf_enabled (caf_mode))
8399 tmp = build_fold_indirect_ref_loc (input_location,
8400 gfc_conv_array_data (dest));
8401 dref = gfc_build_array_ref (tmp, index, NULL);
8402 tmp = structure_alloc_comps (der_type, vref, dref, rank,
8403 COPY_ALLOC_COMP, 0);
8405 else
8406 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose,
8407 caf_mode);
8409 gfc_add_expr_to_block (&loopbody, tmp);
8411 /* Build the loop and return. */
8412 gfc_init_loopinfo (&loop);
8413 loop.dimen = 1;
8414 loop.from[0] = gfc_index_zero_node;
8415 loop.loopvar[0] = index;
8416 loop.to[0] = nelems;
8417 gfc_trans_scalarizing_loops (&loop, &loopbody);
8418 gfc_add_block_to_block (&fnblock, &loop.pre);
8420 tmp = gfc_finish_block (&fnblock);
8421 /* When copying allocateable components, the above implements the
8422 deep copy. Nevertheless is a deep copy only allowed, when the current
8423 component is allocated, for which code will be generated in
8424 gfc_duplicate_allocatable (), where the deep copy code is just added
8425 into the if's body, by adding tmp (the deep copy code) as last
8426 argument to gfc_duplicate_allocatable (). */
8427 if (purpose == COPY_ALLOC_COMP
8428 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
8429 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank,
8430 tmp);
8431 else if (null_cond != NULL_TREE)
8432 tmp = build3_v (COND_EXPR, null_cond, tmp,
8433 build_empty_stmt (input_location));
8435 return tmp;
8438 if (purpose == DEALLOCATE_ALLOC_COMP && der_type->attr.pdt_type)
8440 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
8441 DEALLOCATE_PDT_COMP, 0);
8442 gfc_add_expr_to_block (&fnblock, tmp);
8444 else if (purpose == ALLOCATE_PDT_COMP && der_type->attr.alloc_comp)
8446 tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
8447 NULLIFY_ALLOC_COMP, 0);
8448 gfc_add_expr_to_block (&fnblock, tmp);
8451 /* Otherwise, act on the components or recursively call self to
8452 act on a chain of components. */
8453 for (c = der_type->components; c; c = c->next)
8455 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
8456 || c->ts.type == BT_CLASS)
8457 && c->ts.u.derived->attr.alloc_comp;
8458 bool same_type = (c->ts.type == BT_DERIVED && der_type == c->ts.u.derived)
8459 || (c->ts.type == BT_CLASS && der_type == CLASS_DATA (c)->ts.u.derived);
8461 bool is_pdt_type = c->ts.type == BT_DERIVED
8462 && c->ts.u.derived->attr.pdt_type;
8464 cdecl = c->backend_decl;
8465 ctype = TREE_TYPE (cdecl);
8467 switch (purpose)
8469 case DEALLOCATE_ALLOC_COMP:
8471 gfc_init_block (&tmpblock);
8473 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8474 decl, cdecl, NULL_TREE);
8476 /* Shortcut to get the attributes of the component. */
8477 if (c->ts.type == BT_CLASS)
8479 attr = &CLASS_DATA (c)->attr;
8480 if (attr->class_pointer)
8481 continue;
8483 else
8485 attr = &c->attr;
8486 if (attr->pointer)
8487 continue;
8490 if ((c->ts.type == BT_DERIVED && !c->attr.pointer)
8491 || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer))
8492 /* Call the finalizer, which will free the memory and nullify the
8493 pointer of an array. */
8494 deallocate_called = gfc_add_comp_finalizer_call (&tmpblock, comp, c,
8495 caf_enabled (caf_mode))
8496 && attr->dimension;
8497 else
8498 deallocate_called = false;
8500 /* Add the _class ref for classes. */
8501 if (c->ts.type == BT_CLASS && attr->allocatable)
8502 comp = gfc_class_data_get (comp);
8504 add_when_allocated = NULL_TREE;
8505 if (cmp_has_alloc_comps
8506 && !c->attr.pointer && !c->attr.proc_pointer
8507 && !same_type
8508 && !deallocate_called)
8510 /* Add checked deallocation of the components. This code is
8511 obviously added because the finalizer is not trusted to free
8512 all memory. */
8513 if (c->ts.type == BT_CLASS)
8515 rank = CLASS_DATA (c)->as ? CLASS_DATA (c)->as->rank : 0;
8516 add_when_allocated
8517 = structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
8518 comp, NULL_TREE, rank, purpose,
8519 caf_mode);
8521 else
8523 rank = c->as ? c->as->rank : 0;
8524 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
8525 comp, NULL_TREE,
8526 rank, purpose,
8527 caf_mode);
8531 if (attr->allocatable && !same_type
8532 && (!attr->codimension || caf_enabled (caf_mode)))
8534 /* Handle all types of components besides components of the
8535 same_type as the current one, because those would create an
8536 endless loop. */
8537 caf_dereg_mode
8538 = (caf_in_coarray (caf_mode) || attr->codimension)
8539 ? (gfc_caf_is_dealloc_only (caf_mode)
8540 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
8541 : GFC_CAF_COARRAY_DEREGISTER)
8542 : GFC_CAF_COARRAY_NOCOARRAY;
8544 caf_token = NULL_TREE;
8545 /* Coarray components are handled directly by
8546 deallocate_with_status. */
8547 if (!attr->codimension
8548 && caf_dereg_mode != GFC_CAF_COARRAY_NOCOARRAY)
8550 if (c->caf_token)
8551 caf_token = fold_build3_loc (input_location, COMPONENT_REF,
8552 TREE_TYPE (c->caf_token),
8553 decl, c->caf_token, NULL_TREE);
8554 else if (attr->dimension && !attr->proc_pointer)
8555 caf_token = gfc_conv_descriptor_token (comp);
8557 if (attr->dimension && !attr->codimension && !attr->proc_pointer)
8558 /* When this is an array but not in conjunction with a coarray
8559 then add the data-ref. For coarray'ed arrays the data-ref
8560 is added by deallocate_with_status. */
8561 comp = gfc_conv_descriptor_data_get (comp);
8563 tmp = gfc_deallocate_with_status (comp, NULL_TREE, NULL_TREE,
8564 NULL_TREE, NULL_TREE, true,
8565 NULL, caf_dereg_mode,
8566 add_when_allocated, caf_token);
8568 gfc_add_expr_to_block (&tmpblock, tmp);
8570 else if (attr->allocatable && !attr->codimension
8571 && !deallocate_called)
8573 /* Case of recursive allocatable derived types. */
8574 tree is_allocated;
8575 tree ubound;
8576 tree cdesc;
8577 stmtblock_t dealloc_block;
8579 gfc_init_block (&dealloc_block);
8580 if (add_when_allocated)
8581 gfc_add_expr_to_block (&dealloc_block, add_when_allocated);
8583 /* Convert the component into a rank 1 descriptor type. */
8584 if (attr->dimension)
8586 tmp = gfc_get_element_type (TREE_TYPE (comp));
8587 ubound = gfc_full_array_size (&dealloc_block, comp,
8588 c->ts.type == BT_CLASS
8589 ? CLASS_DATA (c)->as->rank
8590 : c->as->rank);
8592 else
8594 tmp = TREE_TYPE (comp);
8595 ubound = build_int_cst (gfc_array_index_type, 1);
8598 cdesc = gfc_get_array_type_bounds (tmp, 1, 0, &gfc_index_one_node,
8599 &ubound, 1,
8600 GFC_ARRAY_ALLOCATABLE, false);
8602 cdesc = gfc_create_var (cdesc, "cdesc");
8603 DECL_ARTIFICIAL (cdesc) = 1;
8605 gfc_add_modify (&dealloc_block, gfc_conv_descriptor_dtype (cdesc),
8606 gfc_get_dtype_rank_type (1, tmp));
8607 gfc_conv_descriptor_lbound_set (&dealloc_block, cdesc,
8608 gfc_index_zero_node,
8609 gfc_index_one_node);
8610 gfc_conv_descriptor_stride_set (&dealloc_block, cdesc,
8611 gfc_index_zero_node,
8612 gfc_index_one_node);
8613 gfc_conv_descriptor_ubound_set (&dealloc_block, cdesc,
8614 gfc_index_zero_node, ubound);
8616 if (attr->dimension)
8617 comp = gfc_conv_descriptor_data_get (comp);
8619 gfc_conv_descriptor_data_set (&dealloc_block, cdesc, comp);
8621 /* Now call the deallocator. */
8622 vtab = gfc_find_vtab (&c->ts);
8623 if (vtab->backend_decl == NULL)
8624 gfc_get_symbol_decl (vtab);
8625 tmp = gfc_build_addr_expr (NULL_TREE, vtab->backend_decl);
8626 dealloc_fndecl = gfc_vptr_deallocate_get (tmp);
8627 dealloc_fndecl = build_fold_indirect_ref_loc (input_location,
8628 dealloc_fndecl);
8629 tmp = build_int_cst (TREE_TYPE (comp), 0);
8630 is_allocated = fold_build2_loc (input_location, NE_EXPR,
8631 logical_type_node, tmp,
8632 comp);
8633 cdesc = gfc_build_addr_expr (NULL_TREE, cdesc);
8635 tmp = build_call_expr_loc (input_location,
8636 dealloc_fndecl, 1,
8637 cdesc);
8638 gfc_add_expr_to_block (&dealloc_block, tmp);
8640 tmp = gfc_finish_block (&dealloc_block);
8642 tmp = fold_build3_loc (input_location, COND_EXPR,
8643 void_type_node, is_allocated, tmp,
8644 build_empty_stmt (input_location));
8646 gfc_add_expr_to_block (&tmpblock, tmp);
8648 else if (add_when_allocated)
8649 gfc_add_expr_to_block (&tmpblock, add_when_allocated);
8651 if (c->ts.type == BT_CLASS && attr->allocatable
8652 && (!attr->codimension || !caf_enabled (caf_mode)))
8654 /* Finally, reset the vptr to the declared type vtable and, if
8655 necessary reset the _len field.
8657 First recover the reference to the component and obtain
8658 the vptr. */
8659 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8660 decl, cdecl, NULL_TREE);
8661 tmp = gfc_class_vptr_get (comp);
8663 if (UNLIMITED_POLY (c))
8665 /* Both vptr and _len field should be nulled. */
8666 gfc_add_modify (&tmpblock, tmp,
8667 build_int_cst (TREE_TYPE (tmp), 0));
8668 tmp = gfc_class_len_get (comp);
8669 gfc_add_modify (&tmpblock, tmp,
8670 build_int_cst (TREE_TYPE (tmp), 0));
8672 else
8674 /* Build the vtable address and set the vptr with it. */
8675 tree vtab;
8676 gfc_symbol *vtable;
8677 vtable = gfc_find_derived_vtab (c->ts.u.derived);
8678 vtab = vtable->backend_decl;
8679 if (vtab == NULL_TREE)
8680 vtab = gfc_get_symbol_decl (vtable);
8681 vtab = gfc_build_addr_expr (NULL, vtab);
8682 vtab = fold_convert (TREE_TYPE (tmp), vtab);
8683 gfc_add_modify (&tmpblock, tmp, vtab);
8687 /* Now add the deallocation of this component. */
8688 gfc_add_block_to_block (&fnblock, &tmpblock);
8689 break;
8691 case NULLIFY_ALLOC_COMP:
8692 /* Nullify
8693 - allocatable components (regular or in class)
8694 - components that have allocatable components
8695 - pointer components when in a coarray.
8696 Skip everything else especially proc_pointers, which may come
8697 coupled with the regular pointer attribute. */
8698 if (c->attr.proc_pointer
8699 || !(c->attr.allocatable || (c->ts.type == BT_CLASS
8700 && CLASS_DATA (c)->attr.allocatable)
8701 || (cmp_has_alloc_comps
8702 && ((c->ts.type == BT_DERIVED && !c->attr.pointer)
8703 || (c->ts.type == BT_CLASS
8704 && !CLASS_DATA (c)->attr.class_pointer)))
8705 || (caf_in_coarray (caf_mode) && c->attr.pointer)))
8706 continue;
8708 /* Process class components first, because they always have the
8709 pointer-attribute set which would be caught wrong else. */
8710 if (c->ts.type == BT_CLASS
8711 && (CLASS_DATA (c)->attr.allocatable
8712 || CLASS_DATA (c)->attr.class_pointer))
8714 /* Allocatable CLASS components. */
8715 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8716 decl, cdecl, NULL_TREE);
8718 comp = gfc_class_data_get (comp);
8719 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
8720 gfc_conv_descriptor_data_set (&fnblock, comp,
8721 null_pointer_node);
8722 else
8724 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8725 void_type_node, comp,
8726 build_int_cst (TREE_TYPE (comp), 0));
8727 gfc_add_expr_to_block (&fnblock, tmp);
8729 cmp_has_alloc_comps = false;
8731 /* Coarrays need the component to be nulled before the api-call
8732 is made. */
8733 else if (c->attr.pointer || c->attr.allocatable)
8735 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8736 decl, cdecl, NULL_TREE);
8737 if (c->attr.dimension || c->attr.codimension)
8738 gfc_conv_descriptor_data_set (&fnblock, comp,
8739 null_pointer_node);
8740 else
8741 gfc_add_modify (&fnblock, comp,
8742 build_int_cst (TREE_TYPE (comp), 0));
8743 if (gfc_deferred_strlen (c, &comp))
8745 comp = fold_build3_loc (input_location, COMPONENT_REF,
8746 TREE_TYPE (comp),
8747 decl, comp, NULL_TREE);
8748 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8749 TREE_TYPE (comp), comp,
8750 build_int_cst (TREE_TYPE (comp), 0));
8751 gfc_add_expr_to_block (&fnblock, tmp);
8753 cmp_has_alloc_comps = false;
8756 if (flag_coarray == GFC_FCOARRAY_LIB && caf_in_coarray (caf_mode))
8758 /* Register a component of a derived type coarray with the
8759 coarray library. Do not register ultimate component
8760 coarrays here. They are treated like regular coarrays and
8761 are either allocated on all images or on none. */
8762 tree token;
8764 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8765 decl, cdecl, NULL_TREE);
8766 if (c->attr.dimension)
8768 /* Set the dtype, because caf_register needs it. */
8769 gfc_add_modify (&fnblock, gfc_conv_descriptor_dtype (comp),
8770 gfc_get_dtype (TREE_TYPE (comp)));
8771 tmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8772 decl, cdecl, NULL_TREE);
8773 token = gfc_conv_descriptor_token (tmp);
8775 else
8777 gfc_se se;
8779 gfc_init_se (&se, NULL);
8780 token = fold_build3_loc (input_location, COMPONENT_REF,
8781 pvoid_type_node, decl, c->caf_token,
8782 NULL_TREE);
8783 comp = gfc_conv_scalar_to_descriptor (&se, comp,
8784 c->ts.type == BT_CLASS
8785 ? CLASS_DATA (c)->attr
8786 : c->attr);
8787 gfc_add_block_to_block (&fnblock, &se.pre);
8790 gfc_allocate_using_caf_lib (&fnblock, comp, size_zero_node,
8791 gfc_build_addr_expr (NULL_TREE,
8792 token),
8793 NULL_TREE, NULL_TREE, NULL_TREE,
8794 GFC_CAF_COARRAY_ALLOC_REGISTER_ONLY);
8797 if (cmp_has_alloc_comps)
8799 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8800 decl, cdecl, NULL_TREE);
8801 rank = c->as ? c->as->rank : 0;
8802 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
8803 rank, purpose, caf_mode);
8804 gfc_add_expr_to_block (&fnblock, tmp);
8806 break;
8808 case REASSIGN_CAF_COMP:
8809 if (caf_enabled (caf_mode)
8810 && (c->attr.codimension
8811 || (c->ts.type == BT_CLASS
8812 && (CLASS_DATA (c)->attr.coarray_comp
8813 || caf_in_coarray (caf_mode)))
8814 || (c->ts.type == BT_DERIVED
8815 && (c->ts.u.derived->attr.coarray_comp
8816 || caf_in_coarray (caf_mode))))
8817 && !same_type)
8819 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8820 decl, cdecl, NULL_TREE);
8821 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
8822 dest, cdecl, NULL_TREE);
8824 if (c->attr.codimension)
8826 if (c->ts.type == BT_CLASS)
8828 comp = gfc_class_data_get (comp);
8829 dcmp = gfc_class_data_get (dcmp);
8831 gfc_conv_descriptor_data_set (&fnblock, dcmp,
8832 gfc_conv_descriptor_data_get (comp));
8834 else
8836 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
8837 rank, purpose, caf_mode
8838 | GFC_STRUCTURE_CAF_MODE_IN_COARRAY);
8839 gfc_add_expr_to_block (&fnblock, tmp);
8842 break;
8844 case COPY_ALLOC_COMP:
8845 if (c->attr.pointer)
8846 continue;
8848 /* We need source and destination components. */
8849 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
8850 cdecl, NULL_TREE);
8851 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
8852 cdecl, NULL_TREE);
8853 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
8855 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
8857 tree ftn_tree;
8858 tree size;
8859 tree dst_data;
8860 tree src_data;
8861 tree null_data;
8863 dst_data = gfc_class_data_get (dcmp);
8864 src_data = gfc_class_data_get (comp);
8865 size = fold_convert (size_type_node,
8866 gfc_class_vtab_size_get (comp));
8868 if (CLASS_DATA (c)->attr.dimension)
8870 nelems = gfc_conv_descriptor_size (src_data,
8871 CLASS_DATA (c)->as->rank);
8872 size = fold_build2_loc (input_location, MULT_EXPR,
8873 size_type_node, size,
8874 fold_convert (size_type_node,
8875 nelems));
8877 else
8878 nelems = build_int_cst (size_type_node, 1);
8880 if (CLASS_DATA (c)->attr.dimension
8881 || CLASS_DATA (c)->attr.codimension)
8883 src_data = gfc_conv_descriptor_data_get (src_data);
8884 dst_data = gfc_conv_descriptor_data_get (dst_data);
8887 gfc_init_block (&tmpblock);
8889 gfc_add_modify (&tmpblock, gfc_class_vptr_get (dcmp),
8890 gfc_class_vptr_get (comp));
8892 /* Copy the unlimited '_len' field. If it is greater than zero
8893 (ie. a character(_len)), multiply it by size and use this
8894 for the malloc call. */
8895 if (UNLIMITED_POLY (c))
8897 tree ctmp;
8898 gfc_add_modify (&tmpblock, gfc_class_len_get (dcmp),
8899 gfc_class_len_get (comp));
8901 size = gfc_evaluate_now (size, &tmpblock);
8902 tmp = gfc_class_len_get (comp);
8903 ctmp = fold_build2_loc (input_location, MULT_EXPR,
8904 size_type_node, size,
8905 fold_convert (size_type_node, tmp));
8906 tmp = fold_build2_loc (input_location, GT_EXPR,
8907 logical_type_node, tmp,
8908 build_zero_cst (TREE_TYPE (tmp)));
8909 size = fold_build3_loc (input_location, COND_EXPR,
8910 size_type_node, tmp, ctmp, size);
8911 size = gfc_evaluate_now (size, &tmpblock);
8914 /* Coarray component have to have the same allocation status and
8915 shape/type-parameter/effective-type on the LHS and RHS of an
8916 intrinsic assignment. Hence, we did not deallocated them - and
8917 do not allocate them here. */
8918 if (!CLASS_DATA (c)->attr.codimension)
8920 ftn_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
8921 tmp = build_call_expr_loc (input_location, ftn_tree, 1, size);
8922 gfc_add_modify (&tmpblock, dst_data,
8923 fold_convert (TREE_TYPE (dst_data), tmp));
8926 tmp = gfc_copy_class_to_class (comp, dcmp, nelems,
8927 UNLIMITED_POLY (c));
8928 gfc_add_expr_to_block (&tmpblock, tmp);
8929 tmp = gfc_finish_block (&tmpblock);
8931 gfc_init_block (&tmpblock);
8932 gfc_add_modify (&tmpblock, dst_data,
8933 fold_convert (TREE_TYPE (dst_data),
8934 null_pointer_node));
8935 null_data = gfc_finish_block (&tmpblock);
8937 null_cond = fold_build2_loc (input_location, NE_EXPR,
8938 logical_type_node, src_data,
8939 null_pointer_node);
8941 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
8942 tmp, null_data));
8943 continue;
8946 /* To implement guarded deep copy, i.e., deep copy only allocatable
8947 components that are really allocated, the deep copy code has to
8948 be generated first and then added to the if-block in
8949 gfc_duplicate_allocatable (). */
8950 if (cmp_has_alloc_comps && !c->attr.proc_pointer && !same_type)
8952 rank = c->as ? c->as->rank : 0;
8953 tmp = fold_convert (TREE_TYPE (dcmp), comp);
8954 gfc_add_modify (&fnblock, dcmp, tmp);
8955 add_when_allocated = structure_alloc_comps (c->ts.u.derived,
8956 comp, dcmp,
8957 rank, purpose,
8958 caf_mode);
8960 else
8961 add_when_allocated = NULL_TREE;
8963 if (gfc_deferred_strlen (c, &tmp))
8965 tree len, size;
8966 len = tmp;
8967 tmp = fold_build3_loc (input_location, COMPONENT_REF,
8968 TREE_TYPE (len),
8969 decl, len, NULL_TREE);
8970 len = fold_build3_loc (input_location, COMPONENT_REF,
8971 TREE_TYPE (len),
8972 dest, len, NULL_TREE);
8973 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
8974 TREE_TYPE (len), len, tmp);
8975 gfc_add_expr_to_block (&fnblock, tmp);
8976 size = size_of_string_in_bytes (c->ts.kind, len);
8977 /* This component can not have allocatable components,
8978 therefore add_when_allocated of duplicate_allocatable ()
8979 is always NULL. */
8980 tmp = duplicate_allocatable (dcmp, comp, ctype, rank,
8981 false, false, size, NULL_TREE);
8982 gfc_add_expr_to_block (&fnblock, tmp);
8984 else if (c->attr.pdt_array)
8986 tmp = duplicate_allocatable (dcmp, comp, ctype,
8987 c->as ? c->as->rank : 0,
8988 false, false, NULL_TREE, NULL_TREE);
8989 gfc_add_expr_to_block (&fnblock, tmp);
8991 else if ((c->attr.allocatable)
8992 && !c->attr.proc_pointer && !same_type
8993 && (!(cmp_has_alloc_comps && c->as) || c->attr.codimension
8994 || caf_in_coarray (caf_mode)))
8996 rank = c->as ? c->as->rank : 0;
8997 if (c->attr.codimension)
8998 tmp = gfc_copy_allocatable_data (dcmp, comp, ctype, rank);
8999 else if (flag_coarray == GFC_FCOARRAY_LIB
9000 && caf_in_coarray (caf_mode))
9002 tree dst_tok = c->as ? gfc_conv_descriptor_token (dcmp)
9003 : fold_build3_loc (input_location,
9004 COMPONENT_REF,
9005 pvoid_type_node, dest,
9006 c->caf_token,
9007 NULL_TREE);
9008 tmp = duplicate_allocatable_coarray (dcmp, dst_tok, comp,
9009 ctype, rank);
9011 else
9012 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank,
9013 add_when_allocated);
9014 gfc_add_expr_to_block (&fnblock, tmp);
9016 else
9017 if (cmp_has_alloc_comps || is_pdt_type)
9018 gfc_add_expr_to_block (&fnblock, add_when_allocated);
9020 break;
9022 case ALLOCATE_PDT_COMP:
9024 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9025 decl, cdecl, NULL_TREE);
9027 /* Set the PDT KIND and LEN fields. */
9028 if (c->attr.pdt_kind || c->attr.pdt_len)
9030 gfc_se tse;
9031 gfc_expr *c_expr = NULL;
9032 gfc_actual_arglist *param = pdt_param_list;
9033 gfc_init_se (&tse, NULL);
9034 for (; param; param = param->next)
9035 if (param->name && !strcmp (c->name, param->name))
9036 c_expr = param->expr;
9038 if (!c_expr)
9039 c_expr = c->initializer;
9041 if (c_expr)
9043 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
9044 gfc_add_modify (&fnblock, comp, tse.expr);
9048 if (c->attr.pdt_string)
9050 gfc_se tse;
9051 gfc_init_se (&tse, NULL);
9052 tree strlen = NULL_TREE;
9053 gfc_expr *e = gfc_copy_expr (c->ts.u.cl->length);
9054 /* Convert the parameterized string length to its value. The
9055 string length is stored in a hidden field in the same way as
9056 deferred string lengths. */
9057 gfc_insert_parameter_exprs (e, pdt_param_list);
9058 if (gfc_deferred_strlen (c, &strlen) && strlen != NULL_TREE)
9060 gfc_conv_expr_type (&tse, e,
9061 TREE_TYPE (strlen));
9062 strlen = fold_build3_loc (input_location, COMPONENT_REF,
9063 TREE_TYPE (strlen),
9064 decl, strlen, NULL_TREE);
9065 gfc_add_modify (&fnblock, strlen, tse.expr);
9066 c->ts.u.cl->backend_decl = strlen;
9068 gfc_free_expr (e);
9070 /* Scalar parameterized strings can be allocated now. */
9071 if (!c->as)
9073 tmp = fold_convert (gfc_array_index_type, strlen);
9074 tmp = size_of_string_in_bytes (c->ts.kind, tmp);
9075 tmp = gfc_evaluate_now (tmp, &fnblock);
9076 tmp = gfc_call_malloc (&fnblock, TREE_TYPE (comp), tmp);
9077 gfc_add_modify (&fnblock, comp, tmp);
9081 /* Allocate parameterized arrays of parameterized derived types. */
9082 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
9083 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9084 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
9085 continue;
9087 if (c->ts.type == BT_CLASS)
9088 comp = gfc_class_data_get (comp);
9090 if (c->attr.pdt_array)
9092 gfc_se tse;
9093 int i;
9094 tree size = gfc_index_one_node;
9095 tree offset = gfc_index_zero_node;
9096 tree lower, upper;
9097 gfc_expr *e;
9099 /* This chunk takes the expressions for 'lower' and 'upper'
9100 in the arrayspec and substitutes in the expressions for
9101 the parameters from 'pdt_param_list'. The descriptor
9102 fields can then be filled from the values so obtained. */
9103 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)));
9104 for (i = 0; i < c->as->rank; i++)
9106 gfc_init_se (&tse, NULL);
9107 e = gfc_copy_expr (c->as->lower[i]);
9108 gfc_insert_parameter_exprs (e, pdt_param_list);
9109 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9110 gfc_free_expr (e);
9111 lower = tse.expr;
9112 gfc_conv_descriptor_lbound_set (&fnblock, comp,
9113 gfc_rank_cst[i],
9114 lower);
9115 e = gfc_copy_expr (c->as->upper[i]);
9116 gfc_insert_parameter_exprs (e, pdt_param_list);
9117 gfc_conv_expr_type (&tse, e, gfc_array_index_type);
9118 gfc_free_expr (e);
9119 upper = tse.expr;
9120 gfc_conv_descriptor_ubound_set (&fnblock, comp,
9121 gfc_rank_cst[i],
9122 upper);
9123 gfc_conv_descriptor_stride_set (&fnblock, comp,
9124 gfc_rank_cst[i],
9125 size);
9126 size = gfc_evaluate_now (size, &fnblock);
9127 offset = fold_build2_loc (input_location,
9128 MINUS_EXPR,
9129 gfc_array_index_type,
9130 offset, size);
9131 offset = gfc_evaluate_now (offset, &fnblock);
9132 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9133 gfc_array_index_type,
9134 upper, lower);
9135 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9136 gfc_array_index_type,
9137 tmp, gfc_index_one_node);
9138 size = fold_build2_loc (input_location, MULT_EXPR,
9139 gfc_array_index_type, size, tmp);
9141 gfc_conv_descriptor_offset_set (&fnblock, comp, offset);
9142 if (c->ts.type == BT_CLASS)
9144 tmp = gfc_get_vptr_from_expr (comp);
9145 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
9146 tmp = build_fold_indirect_ref_loc (input_location, tmp);
9147 tmp = gfc_vptr_size_get (tmp);
9149 else
9150 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (ctype));
9151 tmp = fold_convert (gfc_array_index_type, tmp);
9152 size = fold_build2_loc (input_location, MULT_EXPR,
9153 gfc_array_index_type, size, tmp);
9154 size = gfc_evaluate_now (size, &fnblock);
9155 tmp = gfc_call_malloc (&fnblock, NULL, size);
9156 gfc_conv_descriptor_data_set (&fnblock, comp, tmp);
9157 tmp = gfc_conv_descriptor_dtype (comp);
9158 gfc_add_modify (&fnblock, tmp, gfc_get_dtype (ctype));
9160 if (c->initializer && c->initializer->rank)
9162 gfc_init_se (&tse, NULL);
9163 e = gfc_copy_expr (c->initializer);
9164 gfc_insert_parameter_exprs (e, pdt_param_list);
9165 gfc_conv_expr_descriptor (&tse, e);
9166 gfc_add_block_to_block (&fnblock, &tse.pre);
9167 gfc_free_expr (e);
9168 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
9169 tmp = build_call_expr_loc (input_location, tmp, 3,
9170 gfc_conv_descriptor_data_get (comp),
9171 gfc_conv_descriptor_data_get (tse.expr),
9172 fold_convert (size_type_node, size));
9173 gfc_add_expr_to_block (&fnblock, tmp);
9174 gfc_add_block_to_block (&fnblock, &tse.post);
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 bool is_deferred = false;
9184 gfc_actual_arglist *tail = c->param_list;
9186 for (; tail; tail = tail->next)
9187 if (!tail->expr)
9188 is_deferred = true;
9190 tail = is_deferred ? pdt_param_list : c->param_list;
9191 tmp = gfc_allocate_pdt_comp (c->ts.u.derived, comp,
9192 c->as ? c->as->rank : 0,
9193 tail);
9194 gfc_add_expr_to_block (&fnblock, tmp);
9197 break;
9199 case DEALLOCATE_PDT_COMP:
9200 /* Deallocate array or parameterized string length components
9201 of parameterized derived types. */
9202 if (!(c->attr.pdt_array && c->as && c->as->type == AS_EXPLICIT)
9203 && !c->attr.pdt_string
9204 && !((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9205 && (c->ts.u.derived && c->ts.u.derived->attr.pdt_type)))
9206 continue;
9208 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9209 decl, cdecl, NULL_TREE);
9210 if (c->ts.type == BT_CLASS)
9211 comp = gfc_class_data_get (comp);
9213 /* Recurse in to PDT components. */
9214 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9215 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type
9216 && (!c->attr.pointer && !c->attr.allocatable))
9218 tmp = gfc_deallocate_pdt_comp (c->ts.u.derived, comp,
9219 c->as ? c->as->rank : 0);
9220 gfc_add_expr_to_block (&fnblock, tmp);
9223 if (c->attr.pdt_array)
9225 tmp = gfc_conv_descriptor_data_get (comp);
9226 null_cond = fold_build2_loc (input_location, NE_EXPR,
9227 logical_type_node, tmp,
9228 build_int_cst (TREE_TYPE (tmp), 0));
9229 tmp = gfc_call_free (tmp);
9230 tmp = build3_v (COND_EXPR, null_cond, tmp,
9231 build_empty_stmt (input_location));
9232 gfc_add_expr_to_block (&fnblock, tmp);
9233 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
9235 else if (c->attr.pdt_string)
9237 null_cond = fold_build2_loc (input_location, NE_EXPR,
9238 logical_type_node, comp,
9239 build_int_cst (TREE_TYPE (comp), 0));
9240 tmp = gfc_call_free (comp);
9241 tmp = build3_v (COND_EXPR, null_cond, tmp,
9242 build_empty_stmt (input_location));
9243 gfc_add_expr_to_block (&fnblock, tmp);
9244 tmp = fold_convert (TREE_TYPE (comp), null_pointer_node);
9245 gfc_add_modify (&fnblock, comp, tmp);
9248 break;
9250 case CHECK_PDT_DUMMY:
9252 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
9253 decl, cdecl, NULL_TREE);
9254 if (c->ts.type == BT_CLASS)
9255 comp = gfc_class_data_get (comp);
9257 /* Recurse in to PDT components. */
9258 if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
9259 && c->ts.u.derived && c->ts.u.derived->attr.pdt_type)
9261 tmp = gfc_check_pdt_dummy (c->ts.u.derived, comp,
9262 c->as ? c->as->rank : 0,
9263 pdt_param_list);
9264 gfc_add_expr_to_block (&fnblock, tmp);
9267 if (!c->attr.pdt_len)
9268 continue;
9269 else
9271 gfc_se tse;
9272 gfc_expr *c_expr = NULL;
9273 gfc_actual_arglist *param = pdt_param_list;
9275 gfc_init_se (&tse, NULL);
9276 for (; param; param = param->next)
9277 if (!strcmp (c->name, param->name)
9278 && param->spec_type == SPEC_EXPLICIT)
9279 c_expr = param->expr;
9281 if (c_expr)
9283 tree error, cond, cname;
9284 gfc_conv_expr_type (&tse, c_expr, TREE_TYPE (comp));
9285 cond = fold_build2_loc (input_location, NE_EXPR,
9286 logical_type_node,
9287 comp, tse.expr);
9288 cname = gfc_build_cstring_const (c->name);
9289 cname = gfc_build_addr_expr (pchar_type_node, cname);
9290 error = gfc_trans_runtime_error (true, NULL,
9291 "The value of the PDT LEN "
9292 "parameter '%s' does not "
9293 "agree with that in the "
9294 "dummy declaration",
9295 cname);
9296 tmp = fold_build3_loc (input_location, COND_EXPR,
9297 void_type_node, cond, error,
9298 build_empty_stmt (input_location));
9299 gfc_add_expr_to_block (&fnblock, tmp);
9302 break;
9304 default:
9305 gcc_unreachable ();
9306 break;
9310 return gfc_finish_block (&fnblock);
9313 /* Recursively traverse an object of derived type, generating code to
9314 nullify allocatable components. */
9316 tree
9317 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
9318 int caf_mode)
9320 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9321 NULLIFY_ALLOC_COMP,
9322 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode);
9326 /* Recursively traverse an object of derived type, generating code to
9327 deallocate allocatable components. */
9329 tree
9330 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
9331 int caf_mode)
9333 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9334 DEALLOCATE_ALLOC_COMP,
9335 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode);
9339 /* Recursively traverse an object of derived type, generating code to
9340 deallocate allocatable components. But do not deallocate coarrays.
9341 To be used for intrinsic assignment, which may not change the allocation
9342 status of coarrays. */
9344 tree
9345 gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank)
9347 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9348 DEALLOCATE_ALLOC_COMP, 0);
9352 tree
9353 gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest)
9355 return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP,
9356 GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY);
9360 /* Recursively traverse an object of derived type, generating code to
9361 copy it and its allocatable components. */
9363 tree
9364 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank,
9365 int caf_mode)
9367 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP,
9368 caf_mode);
9372 /* Recursively traverse an object of derived type, generating code to
9373 copy only its allocatable components. */
9375 tree
9376 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
9378 return structure_alloc_comps (der_type, decl, dest, rank,
9379 COPY_ONLY_ALLOC_COMP, 0);
9383 /* Recursively traverse an object of paramterized derived type, generating
9384 code to allocate parameterized components. */
9386 tree
9387 gfc_allocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank,
9388 gfc_actual_arglist *param_list)
9390 tree res;
9391 gfc_actual_arglist *old_param_list = pdt_param_list;
9392 pdt_param_list = param_list;
9393 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9394 ALLOCATE_PDT_COMP, 0);
9395 pdt_param_list = old_param_list;
9396 return res;
9399 /* Recursively traverse an object of paramterized derived type, generating
9400 code to deallocate parameterized components. */
9402 tree
9403 gfc_deallocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank)
9405 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9406 DEALLOCATE_PDT_COMP, 0);
9410 /* Recursively traverse a dummy of paramterized derived type to check the
9411 values of LEN parameters. */
9413 tree
9414 gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, int rank,
9415 gfc_actual_arglist *param_list)
9417 tree res;
9418 gfc_actual_arglist *old_param_list = pdt_param_list;
9419 pdt_param_list = param_list;
9420 res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
9421 CHECK_PDT_DUMMY, 0);
9422 pdt_param_list = old_param_list;
9423 return res;
9427 /* Returns the value of LBOUND for an expression. This could be broken out
9428 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
9429 called by gfc_alloc_allocatable_for_assignment. */
9430 static tree
9431 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
9433 tree lbound;
9434 tree ubound;
9435 tree stride;
9436 tree cond, cond1, cond3, cond4;
9437 tree tmp;
9438 gfc_ref *ref;
9440 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
9442 tmp = gfc_rank_cst[dim];
9443 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
9444 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
9445 stride = gfc_conv_descriptor_stride_get (desc, tmp);
9446 cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
9447 ubound, lbound);
9448 cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
9449 stride, gfc_index_zero_node);
9450 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
9451 logical_type_node, cond3, cond1);
9452 cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
9453 stride, gfc_index_zero_node);
9454 if (assumed_size)
9455 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9456 tmp, build_int_cst (gfc_array_index_type,
9457 expr->rank - 1));
9458 else
9459 cond = logical_false_node;
9461 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
9462 logical_type_node, cond3, cond4);
9463 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
9464 logical_type_node, cond, cond1);
9466 return fold_build3_loc (input_location, COND_EXPR,
9467 gfc_array_index_type, cond,
9468 lbound, gfc_index_one_node);
9471 if (expr->expr_type == EXPR_FUNCTION)
9473 /* A conversion function, so use the argument. */
9474 gcc_assert (expr->value.function.isym
9475 && expr->value.function.isym->conversion);
9476 expr = expr->value.function.actual->expr;
9479 if (expr->expr_type == EXPR_VARIABLE)
9481 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
9482 for (ref = expr->ref; ref; ref = ref->next)
9484 if (ref->type == REF_COMPONENT
9485 && ref->u.c.component->as
9486 && ref->next
9487 && ref->next->u.ar.type == AR_FULL)
9488 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
9490 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
9493 return gfc_index_one_node;
9497 /* Returns true if an expression represents an lhs that can be reallocated
9498 on assignment. */
9500 bool
9501 gfc_is_reallocatable_lhs (gfc_expr *expr)
9503 gfc_ref * ref;
9504 gfc_symbol *sym;
9506 if (!expr->ref)
9507 return false;
9509 sym = expr->symtree->n.sym;
9511 /* An allocatable class variable with no reference. */
9512 if (sym->ts.type == BT_CLASS
9513 && CLASS_DATA (sym)->attr.allocatable
9514 && expr->ref && expr->ref->type == REF_COMPONENT
9515 && strcmp (expr->ref->u.c.component->name, "_data") == 0
9516 && expr->ref->next == NULL)
9517 return true;
9519 /* An allocatable variable. */
9520 if (sym->attr.allocatable
9521 && expr->ref
9522 && expr->ref->type == REF_ARRAY
9523 && expr->ref->u.ar.type == AR_FULL)
9524 return true;
9526 /* All that can be left are allocatable components. */
9527 if ((sym->ts.type != BT_DERIVED
9528 && sym->ts.type != BT_CLASS)
9529 || !sym->ts.u.derived->attr.alloc_comp)
9530 return false;
9532 /* Find a component ref followed by an array reference. */
9533 for (ref = expr->ref; ref; ref = ref->next)
9534 if (ref->next
9535 && ref->type == REF_COMPONENT
9536 && ref->next->type == REF_ARRAY
9537 && !ref->next->next)
9538 break;
9540 if (!ref)
9541 return false;
9543 /* Return true if valid reallocatable lhs. */
9544 if (ref->u.c.component->attr.allocatable
9545 && ref->next->u.ar.type == AR_FULL)
9546 return true;
9548 return false;
9552 static tree
9553 concat_str_length (gfc_expr* expr)
9555 tree type;
9556 tree len1;
9557 tree len2;
9558 gfc_se se;
9560 type = gfc_typenode_for_spec (&expr->value.op.op1->ts);
9561 len1 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9562 if (len1 == NULL_TREE)
9564 if (expr->value.op.op1->expr_type == EXPR_OP)
9565 len1 = concat_str_length (expr->value.op.op1);
9566 else if (expr->value.op.op1->expr_type == EXPR_CONSTANT)
9567 len1 = build_int_cst (gfc_charlen_type_node,
9568 expr->value.op.op1->value.character.length);
9569 else if (expr->value.op.op1->ts.u.cl->length)
9571 gfc_init_se (&se, NULL);
9572 gfc_conv_expr (&se, expr->value.op.op1->ts.u.cl->length);
9573 len1 = se.expr;
9575 else
9577 /* Last resort! */
9578 gfc_init_se (&se, NULL);
9579 se.want_pointer = 1;
9580 se.descriptor_only = 1;
9581 gfc_conv_expr (&se, expr->value.op.op1);
9582 len1 = se.string_length;
9586 type = gfc_typenode_for_spec (&expr->value.op.op2->ts);
9587 len2 = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9588 if (len2 == NULL_TREE)
9590 if (expr->value.op.op2->expr_type == EXPR_OP)
9591 len2 = concat_str_length (expr->value.op.op2);
9592 else if (expr->value.op.op2->expr_type == EXPR_CONSTANT)
9593 len2 = build_int_cst (gfc_charlen_type_node,
9594 expr->value.op.op2->value.character.length);
9595 else if (expr->value.op.op2->ts.u.cl->length)
9597 gfc_init_se (&se, NULL);
9598 gfc_conv_expr (&se, expr->value.op.op2->ts.u.cl->length);
9599 len2 = se.expr;
9601 else
9603 /* Last resort! */
9604 gfc_init_se (&se, NULL);
9605 se.want_pointer = 1;
9606 se.descriptor_only = 1;
9607 gfc_conv_expr (&se, expr->value.op.op2);
9608 len2 = se.string_length;
9612 gcc_assert(len1 && len2);
9613 len1 = fold_convert (gfc_charlen_type_node, len1);
9614 len2 = fold_convert (gfc_charlen_type_node, len2);
9616 return fold_build2_loc (input_location, PLUS_EXPR,
9617 gfc_charlen_type_node, len1, len2);
9621 /* Allocate the lhs of an assignment to an allocatable array, otherwise
9622 reallocate it. */
9624 tree
9625 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
9626 gfc_expr *expr1,
9627 gfc_expr *expr2)
9629 stmtblock_t realloc_block;
9630 stmtblock_t alloc_block;
9631 stmtblock_t fblock;
9632 gfc_ss *rss;
9633 gfc_ss *lss;
9634 gfc_array_info *linfo;
9635 tree realloc_expr;
9636 tree alloc_expr;
9637 tree size1;
9638 tree size2;
9639 tree array1;
9640 tree cond_null;
9641 tree cond;
9642 tree tmp;
9643 tree tmp2;
9644 tree lbound;
9645 tree ubound;
9646 tree desc;
9647 tree old_desc;
9648 tree desc2;
9649 tree offset;
9650 tree jump_label1;
9651 tree jump_label2;
9652 tree neq_size;
9653 tree lbd;
9654 int n;
9655 int dim;
9656 gfc_array_spec * as;
9657 bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
9658 && gfc_caf_attr (expr1, true).codimension);
9659 tree token;
9660 gfc_se caf_se;
9662 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
9663 Find the lhs expression in the loop chain and set expr1 and
9664 expr2 accordingly. */
9665 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
9667 expr2 = expr1;
9668 /* Find the ss for the lhs. */
9669 lss = loop->ss;
9670 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
9671 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
9672 break;
9673 if (lss == gfc_ss_terminator)
9674 return NULL_TREE;
9675 expr1 = lss->info->expr;
9678 /* Bail out if this is not a valid allocate on assignment. */
9679 if (!gfc_is_reallocatable_lhs (expr1)
9680 || (expr2 && !expr2->rank))
9681 return NULL_TREE;
9683 /* Find the ss for the lhs. */
9684 lss = loop->ss;
9685 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
9686 if (lss->info->expr == expr1)
9687 break;
9689 if (lss == gfc_ss_terminator)
9690 return NULL_TREE;
9692 linfo = &lss->info->data.array;
9694 /* Find an ss for the rhs. For operator expressions, we see the
9695 ss's for the operands. Any one of these will do. */
9696 rss = loop->ss;
9697 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
9698 if (rss->info->expr != expr1 && rss != loop->temp_ss)
9699 break;
9701 if (expr2 && rss == gfc_ss_terminator)
9702 return NULL_TREE;
9704 /* Ensure that the string length from the current scope is used. */
9705 if (expr2->ts.type == BT_CHARACTER
9706 && expr2->expr_type == EXPR_FUNCTION
9707 && !expr2->value.function.isym)
9708 expr2->ts.u.cl->backend_decl = rss->info->string_length;
9710 gfc_start_block (&fblock);
9712 /* Since the lhs is allocatable, this must be a descriptor type.
9713 Get the data and array size. */
9714 desc = linfo->descriptor;
9715 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
9716 array1 = gfc_conv_descriptor_data_get (desc);
9718 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
9719 deallocated if expr is an array of different shape or any of the
9720 corresponding length type parameter values of variable and expr
9721 differ." This assures F95 compatibility. */
9722 jump_label1 = gfc_build_label_decl (NULL_TREE);
9723 jump_label2 = gfc_build_label_decl (NULL_TREE);
9725 /* Allocate if data is NULL. */
9726 cond_null = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
9727 array1, build_int_cst (TREE_TYPE (array1), 0));
9729 if (expr1->ts.deferred)
9730 cond_null = gfc_evaluate_now (logical_true_node, &fblock);
9731 else
9732 cond_null= gfc_evaluate_now (cond_null, &fblock);
9734 tmp = build3_v (COND_EXPR, cond_null,
9735 build1_v (GOTO_EXPR, jump_label1),
9736 build_empty_stmt (input_location));
9737 gfc_add_expr_to_block (&fblock, tmp);
9739 /* Get arrayspec if expr is a full array. */
9740 if (expr2 && expr2->expr_type == EXPR_FUNCTION
9741 && expr2->value.function.isym
9742 && expr2->value.function.isym->conversion)
9744 /* For conversion functions, take the arg. */
9745 gfc_expr *arg = expr2->value.function.actual->expr;
9746 as = gfc_get_full_arrayspec_from_expr (arg);
9748 else if (expr2)
9749 as = gfc_get_full_arrayspec_from_expr (expr2);
9750 else
9751 as = NULL;
9753 /* If the lhs shape is not the same as the rhs jump to setting the
9754 bounds and doing the reallocation....... */
9755 for (n = 0; n < expr1->rank; n++)
9757 /* Check the shape. */
9758 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
9759 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
9760 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9761 gfc_array_index_type,
9762 loop->to[n], loop->from[n]);
9763 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9764 gfc_array_index_type,
9765 tmp, lbound);
9766 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9767 gfc_array_index_type,
9768 tmp, ubound);
9769 cond = fold_build2_loc (input_location, NE_EXPR,
9770 logical_type_node,
9771 tmp, gfc_index_zero_node);
9772 tmp = build3_v (COND_EXPR, cond,
9773 build1_v (GOTO_EXPR, jump_label1),
9774 build_empty_stmt (input_location));
9775 gfc_add_expr_to_block (&fblock, tmp);
9778 /* ....else jump past the (re)alloc code. */
9779 tmp = build1_v (GOTO_EXPR, jump_label2);
9780 gfc_add_expr_to_block (&fblock, tmp);
9782 /* Add the label to start automatic (re)allocation. */
9783 tmp = build1_v (LABEL_EXPR, jump_label1);
9784 gfc_add_expr_to_block (&fblock, tmp);
9786 /* If the lhs has not been allocated, its bounds will not have been
9787 initialized and so its size is set to zero. */
9788 size1 = gfc_create_var (gfc_array_index_type, NULL);
9789 gfc_init_block (&alloc_block);
9790 gfc_add_modify (&alloc_block, size1, gfc_index_zero_node);
9791 gfc_init_block (&realloc_block);
9792 gfc_add_modify (&realloc_block, size1,
9793 gfc_conv_descriptor_size (desc, expr1->rank));
9794 tmp = build3_v (COND_EXPR, cond_null,
9795 gfc_finish_block (&alloc_block),
9796 gfc_finish_block (&realloc_block));
9797 gfc_add_expr_to_block (&fblock, tmp);
9799 /* Get the rhs size and fix it. */
9800 if (expr2)
9801 desc2 = rss->info->data.array.descriptor;
9802 else
9803 desc2 = NULL_TREE;
9805 size2 = gfc_index_one_node;
9806 for (n = 0; n < expr2->rank; n++)
9808 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9809 gfc_array_index_type,
9810 loop->to[n], loop->from[n]);
9811 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9812 gfc_array_index_type,
9813 tmp, gfc_index_one_node);
9814 size2 = fold_build2_loc (input_location, MULT_EXPR,
9815 gfc_array_index_type,
9816 tmp, size2);
9818 size2 = gfc_evaluate_now (size2, &fblock);
9820 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
9821 size1, size2);
9823 /* If the lhs is deferred length, assume that the element size
9824 changes and force a reallocation. */
9825 if (expr1->ts.deferred)
9826 neq_size = gfc_evaluate_now (logical_true_node, &fblock);
9827 else
9828 neq_size = gfc_evaluate_now (cond, &fblock);
9830 /* Deallocation of allocatable components will have to occur on
9831 reallocation. Fix the old descriptor now. */
9832 if ((expr1->ts.type == BT_DERIVED)
9833 && expr1->ts.u.derived->attr.alloc_comp)
9834 old_desc = gfc_evaluate_now (desc, &fblock);
9835 else
9836 old_desc = NULL_TREE;
9838 /* Now modify the lhs descriptor and the associated scalarizer
9839 variables. F2003 7.4.1.3: "If variable is or becomes an
9840 unallocated allocatable variable, then it is allocated with each
9841 deferred type parameter equal to the corresponding type parameters
9842 of expr , with the shape of expr , and with each lower bound equal
9843 to the corresponding element of LBOUND(expr)."
9844 Reuse size1 to keep a dimension-by-dimension track of the
9845 stride of the new array. */
9846 size1 = gfc_index_one_node;
9847 offset = gfc_index_zero_node;
9849 for (n = 0; n < expr2->rank; n++)
9851 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9852 gfc_array_index_type,
9853 loop->to[n], loop->from[n]);
9854 tmp = fold_build2_loc (input_location, PLUS_EXPR,
9855 gfc_array_index_type,
9856 tmp, gfc_index_one_node);
9858 lbound = gfc_index_one_node;
9859 ubound = tmp;
9861 if (as)
9863 lbd = get_std_lbound (expr2, desc2, n,
9864 as->type == AS_ASSUMED_SIZE);
9865 ubound = fold_build2_loc (input_location,
9866 MINUS_EXPR,
9867 gfc_array_index_type,
9868 ubound, lbound);
9869 ubound = fold_build2_loc (input_location,
9870 PLUS_EXPR,
9871 gfc_array_index_type,
9872 ubound, lbd);
9873 lbound = lbd;
9876 gfc_conv_descriptor_lbound_set (&fblock, desc,
9877 gfc_rank_cst[n],
9878 lbound);
9879 gfc_conv_descriptor_ubound_set (&fblock, desc,
9880 gfc_rank_cst[n],
9881 ubound);
9882 gfc_conv_descriptor_stride_set (&fblock, desc,
9883 gfc_rank_cst[n],
9884 size1);
9885 lbound = gfc_conv_descriptor_lbound_get (desc,
9886 gfc_rank_cst[n]);
9887 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
9888 gfc_array_index_type,
9889 lbound, size1);
9890 offset = fold_build2_loc (input_location, MINUS_EXPR,
9891 gfc_array_index_type,
9892 offset, tmp2);
9893 size1 = fold_build2_loc (input_location, MULT_EXPR,
9894 gfc_array_index_type,
9895 tmp, size1);
9898 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
9899 the array offset is saved and the info.offset is used for a
9900 running offset. Use the saved_offset instead. */
9901 tmp = gfc_conv_descriptor_offset (desc);
9902 gfc_add_modify (&fblock, tmp, offset);
9903 if (linfo->saved_offset
9904 && VAR_P (linfo->saved_offset))
9905 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
9907 /* Now set the deltas for the lhs. */
9908 for (n = 0; n < expr1->rank; n++)
9910 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
9911 dim = lss->dim[n];
9912 tmp = fold_build2_loc (input_location, MINUS_EXPR,
9913 gfc_array_index_type, tmp,
9914 loop->from[dim]);
9915 if (linfo->delta[dim] && VAR_P (linfo->delta[dim]))
9916 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
9919 /* Get the new lhs size in bytes. */
9920 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
9922 if (expr2->ts.deferred)
9924 if (VAR_P (expr2->ts.u.cl->backend_decl))
9925 tmp = expr2->ts.u.cl->backend_decl;
9926 else
9927 tmp = rss->info->string_length;
9929 else
9931 tmp = expr2->ts.u.cl->backend_decl;
9932 if (!tmp && expr2->expr_type == EXPR_OP
9933 && expr2->value.op.op == INTRINSIC_CONCAT)
9935 tmp = concat_str_length (expr2);
9936 expr2->ts.u.cl->backend_decl = gfc_evaluate_now (tmp, &fblock);
9938 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
9941 if (expr1->ts.u.cl->backend_decl
9942 && VAR_P (expr1->ts.u.cl->backend_decl))
9943 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
9944 else
9945 gfc_add_modify (&fblock, lss->info->string_length, tmp);
9947 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
9949 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
9950 tmp = fold_build2_loc (input_location, MULT_EXPR,
9951 gfc_array_index_type, tmp,
9952 expr1->ts.u.cl->backend_decl);
9954 else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
9955 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
9956 else
9957 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
9958 tmp = fold_convert (gfc_array_index_type, tmp);
9959 size2 = fold_build2_loc (input_location, MULT_EXPR,
9960 gfc_array_index_type,
9961 tmp, size2);
9962 size2 = fold_convert (size_type_node, size2);
9963 size2 = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
9964 size2, size_one_node);
9965 size2 = gfc_evaluate_now (size2, &fblock);
9967 /* For deferred character length, the 'size' field of the dtype might
9968 have changed so set the dtype. */
9969 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
9970 && expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
9972 tree type;
9973 tmp = gfc_conv_descriptor_dtype (desc);
9974 if (expr2->ts.u.cl->backend_decl)
9975 type = gfc_typenode_for_spec (&expr2->ts);
9976 else
9977 type = gfc_typenode_for_spec (&expr1->ts);
9979 gfc_add_modify (&fblock, tmp,
9980 gfc_get_dtype_rank_type (expr1->rank,type));
9982 else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
9984 tree type;
9985 tmp = gfc_conv_descriptor_dtype (desc);
9986 type = gfc_typenode_for_spec (&expr2->ts);
9987 gfc_add_modify (&fblock, tmp,
9988 gfc_get_dtype_rank_type (expr2->rank,type));
9989 /* Set the _len field as well... */
9990 tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
9991 if (expr2->ts.type == BT_CHARACTER)
9992 gfc_add_modify (&fblock, tmp,
9993 fold_convert (TREE_TYPE (tmp),
9994 TYPE_SIZE_UNIT (type)));
9995 else
9996 gfc_add_modify (&fblock, tmp,
9997 build_int_cst (TREE_TYPE (tmp), 0));
9998 /* ...and the vptr. */
9999 tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
10000 tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
10001 tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
10002 gfc_add_modify (&fblock, tmp, tmp2);
10004 else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
10006 gfc_add_modify (&fblock, gfc_conv_descriptor_dtype (desc),
10007 gfc_get_dtype (TREE_TYPE (desc)));
10010 /* Realloc expression. Note that the scalarizer uses desc.data
10011 in the array reference - (*desc.data)[<element>]. */
10012 gfc_init_block (&realloc_block);
10013 gfc_init_se (&caf_se, NULL);
10015 if (coarray)
10017 token = gfc_get_ultimate_alloc_ptr_comps_caf_token (&caf_se, expr1);
10018 if (token == NULL_TREE)
10020 tmp = gfc_get_tree_for_caf_expr (expr1);
10021 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
10022 tmp = build_fold_indirect_ref (tmp);
10023 gfc_get_caf_token_offset (&caf_se, &token, NULL, tmp, NULL_TREE,
10024 expr1);
10025 token = gfc_build_addr_expr (NULL_TREE, token);
10028 gfc_add_block_to_block (&realloc_block, &caf_se.pre);
10030 if ((expr1->ts.type == BT_DERIVED)
10031 && expr1->ts.u.derived->attr.alloc_comp)
10033 tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc,
10034 expr1->rank);
10035 gfc_add_expr_to_block (&realloc_block, tmp);
10038 if (!coarray)
10040 tmp = build_call_expr_loc (input_location,
10041 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
10042 fold_convert (pvoid_type_node, array1),
10043 size2);
10044 gfc_conv_descriptor_data_set (&realloc_block,
10045 desc, tmp);
10047 else
10049 tmp = build_call_expr_loc (input_location,
10050 gfor_fndecl_caf_deregister, 5, token,
10051 build_int_cst (integer_type_node,
10052 GFC_CAF_COARRAY_DEALLOCATE_ONLY),
10053 null_pointer_node, null_pointer_node,
10054 integer_zero_node);
10055 gfc_add_expr_to_block (&realloc_block, tmp);
10056 tmp = build_call_expr_loc (input_location,
10057 gfor_fndecl_caf_register,
10058 7, size2,
10059 build_int_cst (integer_type_node,
10060 GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY),
10061 token, gfc_build_addr_expr (NULL_TREE, desc),
10062 null_pointer_node, null_pointer_node,
10063 integer_zero_node);
10064 gfc_add_expr_to_block (&realloc_block, tmp);
10067 if ((expr1->ts.type == BT_DERIVED)
10068 && expr1->ts.u.derived->attr.alloc_comp)
10070 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
10071 expr1->rank);
10072 gfc_add_expr_to_block (&realloc_block, tmp);
10075 gfc_add_block_to_block (&realloc_block, &caf_se.post);
10076 realloc_expr = gfc_finish_block (&realloc_block);
10078 /* Only reallocate if sizes are different. */
10079 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
10080 build_empty_stmt (input_location));
10081 realloc_expr = tmp;
10084 /* Malloc expression. */
10085 gfc_init_block (&alloc_block);
10086 if (!coarray)
10088 tmp = build_call_expr_loc (input_location,
10089 builtin_decl_explicit (BUILT_IN_MALLOC),
10090 1, size2);
10091 gfc_conv_descriptor_data_set (&alloc_block,
10092 desc, tmp);
10094 else
10096 tmp = build_call_expr_loc (input_location,
10097 gfor_fndecl_caf_register,
10098 7, size2,
10099 build_int_cst (integer_type_node,
10100 GFC_CAF_COARRAY_ALLOC),
10101 token, gfc_build_addr_expr (NULL_TREE, desc),
10102 null_pointer_node, null_pointer_node,
10103 integer_zero_node);
10104 gfc_add_expr_to_block (&alloc_block, tmp);
10108 /* We already set the dtype in the case of deferred character
10109 length arrays and unlimited polymorphic arrays. */
10110 if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
10111 && ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
10112 || coarray))
10113 && !UNLIMITED_POLY (expr1))
10115 tmp = gfc_conv_descriptor_dtype (desc);
10116 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
10119 if ((expr1->ts.type == BT_DERIVED)
10120 && expr1->ts.u.derived->attr.alloc_comp)
10122 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
10123 expr1->rank);
10124 gfc_add_expr_to_block (&alloc_block, tmp);
10126 alloc_expr = gfc_finish_block (&alloc_block);
10128 /* Malloc if not allocated; realloc otherwise. */
10129 tmp = build_int_cst (TREE_TYPE (array1), 0);
10130 cond = fold_build2_loc (input_location, EQ_EXPR,
10131 logical_type_node,
10132 array1, tmp);
10133 tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
10134 gfc_add_expr_to_block (&fblock, tmp);
10136 /* Make sure that the scalarizer data pointer is updated. */
10137 if (linfo->data && VAR_P (linfo->data))
10139 tmp = gfc_conv_descriptor_data_get (desc);
10140 gfc_add_modify (&fblock, linfo->data, tmp);
10143 /* Add the exit label. */
10144 tmp = build1_v (LABEL_EXPR, jump_label2);
10145 gfc_add_expr_to_block (&fblock, tmp);
10147 return gfc_finish_block (&fblock);
10151 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
10152 Do likewise, recursively if necessary, with the allocatable components of
10153 derived types. */
10155 void
10156 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
10158 tree type;
10159 tree tmp;
10160 tree descriptor;
10161 stmtblock_t init;
10162 stmtblock_t cleanup;
10163 locus loc;
10164 int rank;
10165 bool sym_has_alloc_comp, has_finalizer;
10167 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
10168 || sym->ts.type == BT_CLASS)
10169 && sym->ts.u.derived->attr.alloc_comp;
10170 has_finalizer = sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED
10171 ? gfc_is_finalizable (sym->ts.u.derived, NULL) : false;
10173 /* Make sure the frontend gets these right. */
10174 gcc_assert (sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp
10175 || has_finalizer);
10177 gfc_save_backend_locus (&loc);
10178 gfc_set_backend_locus (&sym->declared_at);
10179 gfc_init_block (&init);
10181 gcc_assert (VAR_P (sym->backend_decl)
10182 || TREE_CODE (sym->backend_decl) == PARM_DECL);
10184 if (sym->ts.type == BT_CHARACTER
10185 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
10187 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
10188 gfc_trans_vla_type_sizes (sym, &init);
10191 /* Dummy, use associated and result variables don't need anything special. */
10192 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
10194 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
10195 gfc_restore_backend_locus (&loc);
10196 return;
10199 descriptor = sym->backend_decl;
10201 /* Although static, derived types with default initializers and
10202 allocatable components must not be nulled wholesale; instead they
10203 are treated component by component. */
10204 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp && !has_finalizer)
10206 /* SAVEd variables are not freed on exit. */
10207 gfc_trans_static_array_pointer (sym);
10209 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
10210 gfc_restore_backend_locus (&loc);
10211 return;
10214 /* Get the descriptor type. */
10215 type = TREE_TYPE (sym->backend_decl);
10217 if ((sym_has_alloc_comp || (has_finalizer && sym->ts.type != BT_CLASS))
10218 && !(sym->attr.pointer || sym->attr.allocatable))
10220 if (!sym->attr.save
10221 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
10223 if (sym->value == NULL
10224 || !gfc_has_default_initializer (sym->ts.u.derived))
10226 rank = sym->as ? sym->as->rank : 0;
10227 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
10228 descriptor, rank);
10229 gfc_add_expr_to_block (&init, tmp);
10231 else
10232 gfc_init_default_dt (sym, &init, false);
10235 else if (!GFC_DESCRIPTOR_TYPE_P (type))
10237 /* If the backend_decl is not a descriptor, we must have a pointer
10238 to one. */
10239 descriptor = build_fold_indirect_ref_loc (input_location,
10240 sym->backend_decl);
10241 type = TREE_TYPE (descriptor);
10244 /* NULLIFY the data pointer, for non-saved allocatables. */
10245 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save && sym->attr.allocatable)
10247 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
10248 if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
10250 /* Declare the variable static so its array descriptor stays present
10251 after leaving the scope. It may still be accessed through another
10252 image. This may happen, for example, with the caf_mpi
10253 implementation. */
10254 TREE_STATIC (descriptor) = 1;
10255 tmp = gfc_conv_descriptor_token (descriptor);
10256 gfc_add_modify (&init, tmp, fold_convert (TREE_TYPE (tmp),
10257 null_pointer_node));
10261 gfc_restore_backend_locus (&loc);
10262 gfc_init_block (&cleanup);
10264 /* Allocatable arrays need to be freed when they go out of scope.
10265 The allocatable components of pointers must not be touched. */
10266 if (!sym->attr.allocatable && has_finalizer && sym->ts.type != BT_CLASS
10267 && !sym->attr.pointer && !sym->attr.artificial && !sym->attr.save
10268 && !sym->ns->proc_name->attr.is_main_program)
10270 gfc_expr *e;
10271 sym->attr.referenced = 1;
10272 e = gfc_lval_expr_from_sym (sym);
10273 gfc_add_finalizer_call (&cleanup, e);
10274 gfc_free_expr (e);
10276 else if ((!sym->attr.allocatable || !has_finalizer)
10277 && sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
10278 && !sym->attr.pointer && !sym->attr.save
10279 && !sym->ns->proc_name->attr.is_main_program)
10281 int rank;
10282 rank = sym->as ? sym->as->rank : 0;
10283 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
10284 gfc_add_expr_to_block (&cleanup, tmp);
10287 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
10288 && !sym->attr.save && !sym->attr.result
10289 && !sym->ns->proc_name->attr.is_main_program)
10291 gfc_expr *e;
10292 e = has_finalizer ? gfc_lval_expr_from_sym (sym) : NULL;
10293 tmp = gfc_deallocate_with_status (sym->backend_decl, NULL_TREE, NULL_TREE,
10294 NULL_TREE, NULL_TREE, true, e,
10295 sym->attr.codimension
10296 ? GFC_CAF_COARRAY_DEREGISTER
10297 : GFC_CAF_COARRAY_NOCOARRAY);
10298 if (e)
10299 gfc_free_expr (e);
10300 gfc_add_expr_to_block (&cleanup, tmp);
10303 gfc_add_init_cleanup (block, gfc_finish_block (&init),
10304 gfc_finish_block (&cleanup));
10307 /************ Expression Walking Functions ******************/
10309 /* Walk a variable reference.
10311 Possible extension - multiple component subscripts.
10312 x(:,:) = foo%a(:)%b(:)
10313 Transforms to
10314 forall (i=..., j=...)
10315 x(i,j) = foo%a(j)%b(i)
10316 end forall
10317 This adds a fair amount of complexity because you need to deal with more
10318 than one ref. Maybe handle in a similar manner to vector subscripts.
10319 Maybe not worth the effort. */
10322 static gfc_ss *
10323 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
10325 gfc_ref *ref;
10327 for (ref = expr->ref; ref; ref = ref->next)
10328 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
10329 break;
10331 return gfc_walk_array_ref (ss, expr, ref);
10335 gfc_ss *
10336 gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
10338 gfc_array_ref *ar;
10339 gfc_ss *newss;
10340 int n;
10342 for (; ref; ref = ref->next)
10344 if (ref->type == REF_SUBSTRING)
10346 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
10347 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
10350 /* We're only interested in array sections from now on. */
10351 if (ref->type != REF_ARRAY)
10352 continue;
10354 ar = &ref->u.ar;
10356 switch (ar->type)
10358 case AR_ELEMENT:
10359 for (n = ar->dimen - 1; n >= 0; n--)
10360 ss = gfc_get_scalar_ss (ss, ar->start[n]);
10361 break;
10363 case AR_FULL:
10364 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
10365 newss->info->data.array.ref = ref;
10367 /* Make sure array is the same as array(:,:), this way
10368 we don't need to special case all the time. */
10369 ar->dimen = ar->as->rank;
10370 for (n = 0; n < ar->dimen; n++)
10372 ar->dimen_type[n] = DIMEN_RANGE;
10374 gcc_assert (ar->start[n] == NULL);
10375 gcc_assert (ar->end[n] == NULL);
10376 gcc_assert (ar->stride[n] == NULL);
10378 ss = newss;
10379 break;
10381 case AR_SECTION:
10382 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
10383 newss->info->data.array.ref = ref;
10385 /* We add SS chains for all the subscripts in the section. */
10386 for (n = 0; n < ar->dimen; n++)
10388 gfc_ss *indexss;
10390 switch (ar->dimen_type[n])
10392 case DIMEN_ELEMENT:
10393 /* Add SS for elemental (scalar) subscripts. */
10394 gcc_assert (ar->start[n]);
10395 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
10396 indexss->loop_chain = gfc_ss_terminator;
10397 newss->info->data.array.subscript[n] = indexss;
10398 break;
10400 case DIMEN_RANGE:
10401 /* We don't add anything for sections, just remember this
10402 dimension for later. */
10403 newss->dim[newss->dimen] = n;
10404 newss->dimen++;
10405 break;
10407 case DIMEN_VECTOR:
10408 /* Create a GFC_SS_VECTOR index in which we can store
10409 the vector's descriptor. */
10410 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
10411 1, GFC_SS_VECTOR);
10412 indexss->loop_chain = gfc_ss_terminator;
10413 newss->info->data.array.subscript[n] = indexss;
10414 newss->dim[newss->dimen] = n;
10415 newss->dimen++;
10416 break;
10418 default:
10419 /* We should know what sort of section it is by now. */
10420 gcc_unreachable ();
10423 /* We should have at least one non-elemental dimension,
10424 unless we are creating a descriptor for a (scalar) coarray. */
10425 gcc_assert (newss->dimen > 0
10426 || newss->info->data.array.ref->u.ar.as->corank > 0);
10427 ss = newss;
10428 break;
10430 default:
10431 /* We should know what sort of section it is by now. */
10432 gcc_unreachable ();
10436 return ss;
10440 /* Walk an expression operator. If only one operand of a binary expression is
10441 scalar, we must also add the scalar term to the SS chain. */
10443 static gfc_ss *
10444 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
10446 gfc_ss *head;
10447 gfc_ss *head2;
10449 head = gfc_walk_subexpr (ss, expr->value.op.op1);
10450 if (expr->value.op.op2 == NULL)
10451 head2 = head;
10452 else
10453 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
10455 /* All operands are scalar. Pass back and let the caller deal with it. */
10456 if (head2 == ss)
10457 return head2;
10459 /* All operands require scalarization. */
10460 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
10461 return head2;
10463 /* One of the operands needs scalarization, the other is scalar.
10464 Create a gfc_ss for the scalar expression. */
10465 if (head == ss)
10467 /* First operand is scalar. We build the chain in reverse order, so
10468 add the scalar SS after the second operand. */
10469 head = head2;
10470 while (head && head->next != ss)
10471 head = head->next;
10472 /* Check we haven't somehow broken the chain. */
10473 gcc_assert (head);
10474 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
10476 else /* head2 == head */
10478 gcc_assert (head2 == head);
10479 /* Second operand is scalar. */
10480 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
10483 return head2;
10487 /* Reverse a SS chain. */
10489 gfc_ss *
10490 gfc_reverse_ss (gfc_ss * ss)
10492 gfc_ss *next;
10493 gfc_ss *head;
10495 gcc_assert (ss != NULL);
10497 head = gfc_ss_terminator;
10498 while (ss != gfc_ss_terminator)
10500 next = ss->next;
10501 /* Check we didn't somehow break the chain. */
10502 gcc_assert (next != NULL);
10503 ss->next = head;
10504 head = ss;
10505 ss = next;
10508 return (head);
10512 /* Given an expression referring to a procedure, return the symbol of its
10513 interface. We can't get the procedure symbol directly as we have to handle
10514 the case of (deferred) type-bound procedures. */
10516 gfc_symbol *
10517 gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
10519 gfc_symbol *sym;
10520 gfc_ref *ref;
10522 if (procedure_ref == NULL)
10523 return NULL;
10525 /* Normal procedure case. */
10526 if (procedure_ref->expr_type == EXPR_FUNCTION
10527 && procedure_ref->value.function.esym)
10528 sym = procedure_ref->value.function.esym;
10529 else
10530 sym = procedure_ref->symtree->n.sym;
10532 /* Typebound procedure case. */
10533 for (ref = procedure_ref->ref; ref; ref = ref->next)
10535 if (ref->type == REF_COMPONENT
10536 && ref->u.c.component->attr.proc_pointer)
10537 sym = ref->u.c.component->ts.interface;
10538 else
10539 sym = NULL;
10542 return sym;
10546 /* Walk the arguments of an elemental function.
10547 PROC_EXPR is used to check whether an argument is permitted to be absent. If
10548 it is NULL, we don't do the check and the argument is assumed to be present.
10551 gfc_ss *
10552 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
10553 gfc_symbol *proc_ifc, gfc_ss_type type)
10555 gfc_formal_arglist *dummy_arg;
10556 int scalar;
10557 gfc_ss *head;
10558 gfc_ss *tail;
10559 gfc_ss *newss;
10561 head = gfc_ss_terminator;
10562 tail = NULL;
10564 if (proc_ifc)
10565 dummy_arg = gfc_sym_get_dummy_args (proc_ifc);
10566 else
10567 dummy_arg = NULL;
10569 scalar = 1;
10570 for (; arg; arg = arg->next)
10572 if (!arg->expr || arg->expr->expr_type == EXPR_NULL)
10573 goto loop_continue;
10575 newss = gfc_walk_subexpr (head, arg->expr);
10576 if (newss == head)
10578 /* Scalar argument. */
10579 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
10580 newss = gfc_get_scalar_ss (head, arg->expr);
10581 newss->info->type = type;
10582 if (dummy_arg)
10583 newss->info->data.scalar.dummy_arg = dummy_arg->sym;
10585 else
10586 scalar = 0;
10588 if (dummy_arg != NULL
10589 && dummy_arg->sym->attr.optional
10590 && arg->expr->expr_type == EXPR_VARIABLE
10591 && (gfc_expr_attr (arg->expr).optional
10592 || gfc_expr_attr (arg->expr).allocatable
10593 || gfc_expr_attr (arg->expr).pointer))
10594 newss->info->can_be_null_ref = true;
10596 head = newss;
10597 if (!tail)
10599 tail = head;
10600 while (tail->next != gfc_ss_terminator)
10601 tail = tail->next;
10604 loop_continue:
10605 if (dummy_arg != NULL)
10606 dummy_arg = dummy_arg->next;
10609 if (scalar)
10611 /* If all the arguments are scalar we don't need the argument SS. */
10612 gfc_free_ss_chain (head);
10613 /* Pass it back. */
10614 return ss;
10617 /* Add it onto the existing chain. */
10618 tail->next = ss;
10619 return head;
10623 /* Walk a function call. Scalar functions are passed back, and taken out of
10624 scalarization loops. For elemental functions we walk their arguments.
10625 The result of functions returning arrays is stored in a temporary outside
10626 the loop, so that the function is only called once. Hence we do not need
10627 to walk their arguments. */
10629 static gfc_ss *
10630 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
10632 gfc_intrinsic_sym *isym;
10633 gfc_symbol *sym;
10634 gfc_component *comp = NULL;
10636 isym = expr->value.function.isym;
10638 /* Handle intrinsic functions separately. */
10639 if (isym)
10640 return gfc_walk_intrinsic_function (ss, expr, isym);
10642 sym = expr->value.function.esym;
10643 if (!sym)
10644 sym = expr->symtree->n.sym;
10646 if (gfc_is_class_array_function (expr))
10647 return gfc_get_array_ss (ss, expr,
10648 CLASS_DATA (expr->value.function.esym->result)->as->rank,
10649 GFC_SS_FUNCTION);
10651 /* A function that returns arrays. */
10652 comp = gfc_get_proc_ptr_comp (expr);
10653 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
10654 || (comp && comp->attr.dimension))
10655 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
10657 /* Walk the parameters of an elemental function. For now we always pass
10658 by reference. */
10659 if (sym->attr.elemental || (comp && comp->attr.elemental))
10661 gfc_ss *old_ss = ss;
10663 ss = gfc_walk_elemental_function_args (old_ss,
10664 expr->value.function.actual,
10665 gfc_get_proc_ifc_for_expr (expr),
10666 GFC_SS_REFERENCE);
10667 if (ss != old_ss
10668 && (comp
10669 || sym->attr.proc_pointer
10670 || sym->attr.if_source != IFSRC_DECL
10671 || sym->attr.array_outer_dependency))
10672 ss->info->array_outer_dependency = 1;
10675 /* Scalar functions are OK as these are evaluated outside the scalarization
10676 loop. Pass back and let the caller deal with it. */
10677 return ss;
10681 /* An array temporary is constructed for array constructors. */
10683 static gfc_ss *
10684 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
10686 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
10690 /* Walk an expression. Add walked expressions to the head of the SS chain.
10691 A wholly scalar expression will not be added. */
10693 gfc_ss *
10694 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
10696 gfc_ss *head;
10698 switch (expr->expr_type)
10700 case EXPR_VARIABLE:
10701 head = gfc_walk_variable_expr (ss, expr);
10702 return head;
10704 case EXPR_OP:
10705 head = gfc_walk_op_expr (ss, expr);
10706 return head;
10708 case EXPR_FUNCTION:
10709 head = gfc_walk_function_expr (ss, expr);
10710 return head;
10712 case EXPR_CONSTANT:
10713 case EXPR_NULL:
10714 case EXPR_STRUCTURE:
10715 /* Pass back and let the caller deal with it. */
10716 break;
10718 case EXPR_ARRAY:
10719 head = gfc_walk_array_constructor (ss, expr);
10720 return head;
10722 case EXPR_SUBSTRING:
10723 /* Pass back and let the caller deal with it. */
10724 break;
10726 default:
10727 gfc_internal_error ("bad expression type during walk (%d)",
10728 expr->expr_type);
10730 return ss;
10734 /* Entry point for expression walking.
10735 A return value equal to the passed chain means this is
10736 a scalar expression. It is up to the caller to take whatever action is
10737 necessary to translate these. */
10739 gfc_ss *
10740 gfc_walk_expr (gfc_expr * expr)
10742 gfc_ss *res;
10744 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
10745 return gfc_reverse_ss (res);