* trans-array.c (trans_array_bound_check): Use xasprintf instead
[official-gcc.git] / gcc / fortran / trans-array.c
blob07a9873be861d142aa877ccc0951025681314509
1 /* Array translation routines
2 Copyright (C) 2002-2014 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 "gfortran.h"
82 #include "tree.h"
83 #include "gimple-expr.h"
84 #include "diagnostic-core.h" /* For internal_error/fatal_error. */
85 #include "flags.h"
86 #include "constructor.h"
87 #include "trans.h"
88 #include "trans-stmt.h"
89 #include "trans-types.h"
90 #include "trans-array.h"
91 #include "trans-const.h"
92 #include "dependency.h"
93 #include "wide-int.h"
95 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
97 /* The contents of this structure aren't actually used, just the address. */
98 static gfc_ss gfc_ss_terminator_var;
99 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
102 static tree
103 gfc_array_dataptr_type (tree desc)
105 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
109 /* Build expressions to access the members of an array descriptor.
110 It's surprisingly easy to mess up here, so never access
111 an array descriptor by "brute force", always use these
112 functions. This also avoids problems if we change the format
113 of an array descriptor.
115 To understand these magic numbers, look at the comments
116 before gfc_build_array_type() in trans-types.c.
118 The code within these defines should be the only code which knows the format
119 of an array descriptor.
121 Any code just needing to read obtain the bounds of an array should use
122 gfc_conv_array_* rather than the following functions as these will return
123 know constant values, and work with arrays which do not have descriptors.
125 Don't forget to #undef these! */
127 #define DATA_FIELD 0
128 #define OFFSET_FIELD 1
129 #define DTYPE_FIELD 2
130 #define DIMENSION_FIELD 3
131 #define CAF_TOKEN_FIELD 4
133 #define STRIDE_SUBFIELD 0
134 #define LBOUND_SUBFIELD 1
135 #define UBOUND_SUBFIELD 2
137 /* This provides READ-ONLY access to the data field. The field itself
138 doesn't have the proper type. */
140 tree
141 gfc_conv_descriptor_data_get (tree desc)
143 tree field, type, t;
145 type = TREE_TYPE (desc);
146 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
148 field = TYPE_FIELDS (type);
149 gcc_assert (DATA_FIELD == 0);
151 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
152 field, NULL_TREE);
153 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
155 return t;
158 /* This provides WRITE access to the data field.
160 TUPLES_P is true if we are generating tuples.
162 This function gets called through the following macros:
163 gfc_conv_descriptor_data_set
164 gfc_conv_descriptor_data_set. */
166 void
167 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
169 tree field, type, t;
171 type = TREE_TYPE (desc);
172 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
174 field = TYPE_FIELDS (type);
175 gcc_assert (DATA_FIELD == 0);
177 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
178 field, NULL_TREE);
179 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
183 /* This provides address access to the data field. This should only be
184 used by array allocation, passing this on to the runtime. */
186 tree
187 gfc_conv_descriptor_data_addr (tree desc)
189 tree field, type, t;
191 type = TREE_TYPE (desc);
192 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
194 field = TYPE_FIELDS (type);
195 gcc_assert (DATA_FIELD == 0);
197 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
198 field, NULL_TREE);
199 return gfc_build_addr_expr (NULL_TREE, t);
202 static tree
203 gfc_conv_descriptor_offset (tree desc)
205 tree type;
206 tree field;
208 type = TREE_TYPE (desc);
209 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
211 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
212 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
214 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
215 desc, field, NULL_TREE);
218 tree
219 gfc_conv_descriptor_offset_get (tree desc)
221 return gfc_conv_descriptor_offset (desc);
224 void
225 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
226 tree value)
228 tree t = gfc_conv_descriptor_offset (desc);
229 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
233 tree
234 gfc_conv_descriptor_dtype (tree desc)
236 tree field;
237 tree type;
239 type = TREE_TYPE (desc);
240 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
242 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
243 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
245 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
246 desc, field, NULL_TREE);
250 tree
251 gfc_conv_descriptor_rank (tree desc)
253 tree tmp;
254 tree dtype;
256 dtype = gfc_conv_descriptor_dtype (desc);
257 tmp = build_int_cst (TREE_TYPE (dtype), GFC_DTYPE_RANK_MASK);
258 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (dtype),
259 dtype, tmp);
260 return fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
264 tree
265 gfc_get_descriptor_dimension (tree desc)
267 tree type, field;
269 type = TREE_TYPE (desc);
270 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
272 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
273 gcc_assert (field != NULL_TREE
274 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
275 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
277 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
278 desc, field, NULL_TREE);
282 static tree
283 gfc_conv_descriptor_dimension (tree desc, tree dim)
285 tree tmp;
287 tmp = gfc_get_descriptor_dimension (desc);
289 return gfc_build_array_ref (tmp, dim, NULL);
293 tree
294 gfc_conv_descriptor_token (tree desc)
296 tree type;
297 tree field;
299 type = TREE_TYPE (desc);
300 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
301 gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
302 field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
304 /* Should be a restricted pointer - except in the finalization wrapper. */
305 gcc_assert (field != NULL_TREE
306 && (TREE_TYPE (field) == prvoid_type_node
307 || TREE_TYPE (field) == pvoid_type_node));
309 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
310 desc, field, NULL_TREE);
314 static tree
315 gfc_conv_descriptor_stride (tree desc, tree dim)
317 tree tmp;
318 tree field;
320 tmp = gfc_conv_descriptor_dimension (desc, dim);
321 field = TYPE_FIELDS (TREE_TYPE (tmp));
322 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
323 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
325 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
326 tmp, field, NULL_TREE);
327 return tmp;
330 tree
331 gfc_conv_descriptor_stride_get (tree desc, tree dim)
333 tree type = TREE_TYPE (desc);
334 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
335 if (integer_zerop (dim)
336 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
337 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
338 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
339 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
340 return gfc_index_one_node;
342 return gfc_conv_descriptor_stride (desc, dim);
345 void
346 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
347 tree dim, tree value)
349 tree t = gfc_conv_descriptor_stride (desc, dim);
350 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
353 static tree
354 gfc_conv_descriptor_lbound (tree desc, tree dim)
356 tree tmp;
357 tree field;
359 tmp = gfc_conv_descriptor_dimension (desc, dim);
360 field = TYPE_FIELDS (TREE_TYPE (tmp));
361 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
362 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
364 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
365 tmp, field, NULL_TREE);
366 return tmp;
369 tree
370 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
372 return gfc_conv_descriptor_lbound (desc, dim);
375 void
376 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
377 tree dim, tree value)
379 tree t = gfc_conv_descriptor_lbound (desc, dim);
380 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
383 static tree
384 gfc_conv_descriptor_ubound (tree desc, tree dim)
386 tree tmp;
387 tree field;
389 tmp = gfc_conv_descriptor_dimension (desc, dim);
390 field = TYPE_FIELDS (TREE_TYPE (tmp));
391 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
392 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
394 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
395 tmp, field, NULL_TREE);
396 return tmp;
399 tree
400 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
402 return gfc_conv_descriptor_ubound (desc, dim);
405 void
406 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
407 tree dim, tree value)
409 tree t = gfc_conv_descriptor_ubound (desc, dim);
410 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
413 /* Build a null array descriptor constructor. */
415 tree
416 gfc_build_null_descriptor (tree type)
418 tree field;
419 tree tmp;
421 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
422 gcc_assert (DATA_FIELD == 0);
423 field = TYPE_FIELDS (type);
425 /* Set a NULL data pointer. */
426 tmp = build_constructor_single (type, field, null_pointer_node);
427 TREE_CONSTANT (tmp) = 1;
428 /* All other fields are ignored. */
430 return tmp;
434 /* Modify a descriptor such that the lbound of a given dimension is the value
435 specified. This also updates ubound and offset accordingly. */
437 void
438 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
439 int dim, tree new_lbound)
441 tree offs, ubound, lbound, stride;
442 tree diff, offs_diff;
444 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
446 offs = gfc_conv_descriptor_offset_get (desc);
447 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
448 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
449 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
451 /* Get difference (new - old) by which to shift stuff. */
452 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
453 new_lbound, lbound);
455 /* Shift ubound and offset accordingly. This has to be done before
456 updating the lbound, as they depend on the lbound expression! */
457 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
458 ubound, diff);
459 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
460 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
461 diff, stride);
462 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
463 offs, offs_diff);
464 gfc_conv_descriptor_offset_set (block, desc, offs);
466 /* Finally set lbound to value we want. */
467 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
471 /* Cleanup those #defines. */
473 #undef DATA_FIELD
474 #undef OFFSET_FIELD
475 #undef DTYPE_FIELD
476 #undef DIMENSION_FIELD
477 #undef CAF_TOKEN_FIELD
478 #undef STRIDE_SUBFIELD
479 #undef LBOUND_SUBFIELD
480 #undef UBOUND_SUBFIELD
483 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
484 flags & 1 = Main loop body.
485 flags & 2 = temp copy loop. */
487 void
488 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
490 for (; ss != gfc_ss_terminator; ss = ss->next)
491 ss->info->useflags = flags;
495 /* Free a gfc_ss chain. */
497 void
498 gfc_free_ss_chain (gfc_ss * ss)
500 gfc_ss *next;
502 while (ss != gfc_ss_terminator)
504 gcc_assert (ss != NULL);
505 next = ss->next;
506 gfc_free_ss (ss);
507 ss = next;
512 static void
513 free_ss_info (gfc_ss_info *ss_info)
515 int n;
517 ss_info->refcount--;
518 if (ss_info->refcount > 0)
519 return;
521 gcc_assert (ss_info->refcount == 0);
523 switch (ss_info->type)
525 case GFC_SS_SECTION:
526 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
527 if (ss_info->data.array.subscript[n])
528 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
529 break;
531 default:
532 break;
535 free (ss_info);
539 /* Free a SS. */
541 void
542 gfc_free_ss (gfc_ss * ss)
544 free_ss_info (ss->info);
545 free (ss);
549 /* Creates and initializes an array type gfc_ss struct. */
551 gfc_ss *
552 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
554 gfc_ss *ss;
555 gfc_ss_info *ss_info;
556 int i;
558 ss_info = gfc_get_ss_info ();
559 ss_info->refcount++;
560 ss_info->type = type;
561 ss_info->expr = expr;
563 ss = gfc_get_ss ();
564 ss->info = ss_info;
565 ss->next = next;
566 ss->dimen = dimen;
567 for (i = 0; i < ss->dimen; i++)
568 ss->dim[i] = i;
570 return ss;
574 /* Creates and initializes a temporary type gfc_ss struct. */
576 gfc_ss *
577 gfc_get_temp_ss (tree type, tree string_length, int dimen)
579 gfc_ss *ss;
580 gfc_ss_info *ss_info;
581 int i;
583 ss_info = gfc_get_ss_info ();
584 ss_info->refcount++;
585 ss_info->type = GFC_SS_TEMP;
586 ss_info->string_length = string_length;
587 ss_info->data.temp.type = type;
589 ss = gfc_get_ss ();
590 ss->info = ss_info;
591 ss->next = gfc_ss_terminator;
592 ss->dimen = dimen;
593 for (i = 0; i < ss->dimen; i++)
594 ss->dim[i] = i;
596 return ss;
600 /* Creates and initializes a scalar type gfc_ss struct. */
602 gfc_ss *
603 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
605 gfc_ss *ss;
606 gfc_ss_info *ss_info;
608 ss_info = gfc_get_ss_info ();
609 ss_info->refcount++;
610 ss_info->type = GFC_SS_SCALAR;
611 ss_info->expr = expr;
613 ss = gfc_get_ss ();
614 ss->info = ss_info;
615 ss->next = next;
617 return ss;
621 /* Free all the SS associated with a loop. */
623 void
624 gfc_cleanup_loop (gfc_loopinfo * loop)
626 gfc_loopinfo *loop_next, **ploop;
627 gfc_ss *ss;
628 gfc_ss *next;
630 ss = loop->ss;
631 while (ss != gfc_ss_terminator)
633 gcc_assert (ss != NULL);
634 next = ss->loop_chain;
635 gfc_free_ss (ss);
636 ss = next;
639 /* Remove reference to self in the parent loop. */
640 if (loop->parent)
641 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
642 if (*ploop == loop)
644 *ploop = loop->next;
645 break;
648 /* Free non-freed nested loops. */
649 for (loop = loop->nested; loop; loop = loop_next)
651 loop_next = loop->next;
652 gfc_cleanup_loop (loop);
653 free (loop);
658 static void
659 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
661 int n;
663 for (; ss != gfc_ss_terminator; ss = ss->next)
665 ss->loop = loop;
667 if (ss->info->type == GFC_SS_SCALAR
668 || ss->info->type == GFC_SS_REFERENCE
669 || ss->info->type == GFC_SS_TEMP)
670 continue;
672 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
673 if (ss->info->data.array.subscript[n] != NULL)
674 set_ss_loop (ss->info->data.array.subscript[n], loop);
679 /* Associate a SS chain with a loop. */
681 void
682 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
684 gfc_ss *ss;
685 gfc_loopinfo *nested_loop;
687 if (head == gfc_ss_terminator)
688 return;
690 set_ss_loop (head, loop);
692 ss = head;
693 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
695 if (ss->nested_ss)
697 nested_loop = ss->nested_ss->loop;
699 /* More than one ss can belong to the same loop. Hence, we add the
700 loop to the chain only if it is different from the previously
701 added one, to avoid duplicate nested loops. */
702 if (nested_loop != loop->nested)
704 gcc_assert (nested_loop->parent == NULL);
705 nested_loop->parent = loop;
707 gcc_assert (nested_loop->next == NULL);
708 nested_loop->next = loop->nested;
709 loop->nested = nested_loop;
711 else
712 gcc_assert (nested_loop->parent == loop);
715 if (ss->next == gfc_ss_terminator)
716 ss->loop_chain = loop->ss;
717 else
718 ss->loop_chain = ss->next;
720 gcc_assert (ss == gfc_ss_terminator);
721 loop->ss = head;
725 /* Generate an initializer for a static pointer or allocatable array. */
727 void
728 gfc_trans_static_array_pointer (gfc_symbol * sym)
730 tree type;
732 gcc_assert (TREE_STATIC (sym->backend_decl));
733 /* Just zero the data member. */
734 type = TREE_TYPE (sym->backend_decl);
735 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
739 /* If the bounds of SE's loop have not yet been set, see if they can be
740 determined from array spec AS, which is the array spec of a called
741 function. MAPPING maps the callee's dummy arguments to the values
742 that the caller is passing. Add any initialization and finalization
743 code to SE. */
745 void
746 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
747 gfc_se * se, gfc_array_spec * as)
749 int n, dim, total_dim;
750 gfc_se tmpse;
751 gfc_ss *ss;
752 tree lower;
753 tree upper;
754 tree tmp;
756 total_dim = 0;
758 if (!as || as->type != AS_EXPLICIT)
759 return;
761 for (ss = se->ss; ss; ss = ss->parent)
763 total_dim += ss->loop->dimen;
764 for (n = 0; n < ss->loop->dimen; n++)
766 /* The bound is known, nothing to do. */
767 if (ss->loop->to[n] != NULL_TREE)
768 continue;
770 dim = ss->dim[n];
771 gcc_assert (dim < as->rank);
772 gcc_assert (ss->loop->dimen <= as->rank);
774 /* Evaluate the lower bound. */
775 gfc_init_se (&tmpse, NULL);
776 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
777 gfc_add_block_to_block (&se->pre, &tmpse.pre);
778 gfc_add_block_to_block (&se->post, &tmpse.post);
779 lower = fold_convert (gfc_array_index_type, tmpse.expr);
781 /* ...and the upper bound. */
782 gfc_init_se (&tmpse, NULL);
783 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
784 gfc_add_block_to_block (&se->pre, &tmpse.pre);
785 gfc_add_block_to_block (&se->post, &tmpse.post);
786 upper = fold_convert (gfc_array_index_type, tmpse.expr);
788 /* Set the upper bound of the loop to UPPER - LOWER. */
789 tmp = fold_build2_loc (input_location, MINUS_EXPR,
790 gfc_array_index_type, upper, lower);
791 tmp = gfc_evaluate_now (tmp, &se->pre);
792 ss->loop->to[n] = tmp;
796 gcc_assert (total_dim == as->rank);
800 /* Generate code to allocate an array temporary, or create a variable to
801 hold the data. If size is NULL, zero the descriptor so that the
802 callee will allocate the array. If DEALLOC is true, also generate code to
803 free the array afterwards.
805 If INITIAL is not NULL, it is packed using internal_pack and the result used
806 as data instead of allocating a fresh, unitialized area of memory.
808 Initialization code is added to PRE and finalization code to POST.
809 DYNAMIC is true if the caller may want to extend the array later
810 using realloc. This prevents us from putting the array on the stack. */
812 static void
813 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
814 gfc_array_info * info, tree size, tree nelem,
815 tree initial, bool dynamic, bool dealloc)
817 tree tmp;
818 tree desc;
819 bool onstack;
821 desc = info->descriptor;
822 info->offset = gfc_index_zero_node;
823 if (size == NULL_TREE || integer_zerop (size))
825 /* A callee allocated array. */
826 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
827 onstack = FALSE;
829 else
831 /* Allocate the temporary. */
832 onstack = !dynamic && initial == NULL_TREE
833 && (flag_stack_arrays
834 || gfc_can_put_var_on_stack (size));
836 if (onstack)
838 /* Make a temporary variable to hold the data. */
839 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
840 nelem, gfc_index_one_node);
841 tmp = gfc_evaluate_now (tmp, pre);
842 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
843 tmp);
844 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
845 tmp);
846 tmp = gfc_create_var (tmp, "A");
847 /* If we're here only because of -fstack-arrays we have to
848 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
849 if (!gfc_can_put_var_on_stack (size))
850 gfc_add_expr_to_block (pre,
851 fold_build1_loc (input_location,
852 DECL_EXPR, TREE_TYPE (tmp),
853 tmp));
854 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
855 gfc_conv_descriptor_data_set (pre, desc, tmp);
857 else
859 /* Allocate memory to hold the data or call internal_pack. */
860 if (initial == NULL_TREE)
862 tmp = gfc_call_malloc (pre, NULL, size);
863 tmp = gfc_evaluate_now (tmp, pre);
865 else
867 tree packed;
868 tree source_data;
869 tree was_packed;
870 stmtblock_t do_copying;
872 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
873 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
874 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
875 tmp = gfc_get_element_type (tmp);
876 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
877 packed = gfc_create_var (build_pointer_type (tmp), "data");
879 tmp = build_call_expr_loc (input_location,
880 gfor_fndecl_in_pack, 1, initial);
881 tmp = fold_convert (TREE_TYPE (packed), tmp);
882 gfc_add_modify (pre, packed, tmp);
884 tmp = build_fold_indirect_ref_loc (input_location,
885 initial);
886 source_data = gfc_conv_descriptor_data_get (tmp);
888 /* internal_pack may return source->data without any allocation
889 or copying if it is already packed. If that's the case, we
890 need to allocate and copy manually. */
892 gfc_start_block (&do_copying);
893 tmp = gfc_call_malloc (&do_copying, NULL, size);
894 tmp = fold_convert (TREE_TYPE (packed), tmp);
895 gfc_add_modify (&do_copying, packed, tmp);
896 tmp = gfc_build_memcpy_call (packed, source_data, size);
897 gfc_add_expr_to_block (&do_copying, tmp);
899 was_packed = fold_build2_loc (input_location, EQ_EXPR,
900 boolean_type_node, packed,
901 source_data);
902 tmp = gfc_finish_block (&do_copying);
903 tmp = build3_v (COND_EXPR, was_packed, tmp,
904 build_empty_stmt (input_location));
905 gfc_add_expr_to_block (pre, tmp);
907 tmp = fold_convert (pvoid_type_node, packed);
910 gfc_conv_descriptor_data_set (pre, desc, tmp);
913 info->data = gfc_conv_descriptor_data_get (desc);
915 /* The offset is zero because we create temporaries with a zero
916 lower bound. */
917 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
919 if (dealloc && !onstack)
921 /* Free the temporary. */
922 tmp = gfc_conv_descriptor_data_get (desc);
923 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
924 gfc_add_expr_to_block (post, tmp);
929 /* Get the scalarizer array dimension corresponding to actual array dimension
930 given by ARRAY_DIM.
932 For example, if SS represents the array ref a(1,:,:,1), it is a
933 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
934 and 1 for ARRAY_DIM=2.
935 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
936 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
937 ARRAY_DIM=3.
938 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
939 array. If called on the inner ss, the result would be respectively 0,1,2 for
940 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
941 for ARRAY_DIM=1,2. */
943 static int
944 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
946 int array_ref_dim;
947 int n;
949 array_ref_dim = 0;
951 for (; ss; ss = ss->parent)
952 for (n = 0; n < ss->dimen; n++)
953 if (ss->dim[n] < array_dim)
954 array_ref_dim++;
956 return array_ref_dim;
960 static gfc_ss *
961 innermost_ss (gfc_ss *ss)
963 while (ss->nested_ss != NULL)
964 ss = ss->nested_ss;
966 return ss;
971 /* Get the array reference dimension corresponding to the given loop dimension.
972 It is different from the true array dimension given by the dim array in
973 the case of a partial array reference (i.e. a(:,:,1,:) for example)
974 It is different from the loop dimension in the case of a transposed array.
977 static int
978 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
980 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
981 ss->dim[loop_dim]);
985 /* Generate code to create and initialize the descriptor for a temporary
986 array. This is used for both temporaries needed by the scalarizer, and
987 functions returning arrays. Adjusts the loop variables to be
988 zero-based, and calculates the loop bounds for callee allocated arrays.
989 Allocate the array unless it's callee allocated (we have a callee
990 allocated array if 'callee_alloc' is true, or if loop->to[n] is
991 NULL_TREE for any n). Also fills in the descriptor, data and offset
992 fields of info if known. Returns the size of the array, or NULL for a
993 callee allocated array.
995 'eltype' == NULL signals that the temporary should be a class object.
996 The 'initial' expression is used to obtain the size of the dynamic
997 type; otherwise the allocation and initialization proceeds as for any
998 other expression
1000 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
1001 gfc_trans_allocate_array_storage. */
1003 tree
1004 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
1005 tree eltype, tree initial, bool dynamic,
1006 bool dealloc, bool callee_alloc, locus * where)
1008 gfc_loopinfo *loop;
1009 gfc_ss *s;
1010 gfc_array_info *info;
1011 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
1012 tree type;
1013 tree desc;
1014 tree tmp;
1015 tree size;
1016 tree nelem;
1017 tree cond;
1018 tree or_expr;
1019 tree class_expr = NULL_TREE;
1020 int n, dim, tmp_dim;
1021 int total_dim = 0;
1023 /* This signals a class array for which we need the size of the
1024 dynamic type. Generate an eltype and then the class expression. */
1025 if (eltype == NULL_TREE && initial)
1027 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1028 class_expr = build_fold_indirect_ref_loc (input_location, initial);
1029 eltype = TREE_TYPE (class_expr);
1030 eltype = gfc_get_element_type (eltype);
1031 /* Obtain the structure (class) expression. */
1032 class_expr = TREE_OPERAND (class_expr, 0);
1033 gcc_assert (class_expr);
1036 memset (from, 0, sizeof (from));
1037 memset (to, 0, sizeof (to));
1039 info = &ss->info->data.array;
1041 gcc_assert (ss->dimen > 0);
1042 gcc_assert (ss->loop->dimen == ss->dimen);
1044 if (warn_array_temporaries && where)
1045 gfc_warning (OPT_Warray_temporaries,
1046 "Creating array temporary at %L", where);
1048 /* Set the lower bound to zero. */
1049 for (s = ss; s; s = s->parent)
1051 loop = s->loop;
1053 total_dim += loop->dimen;
1054 for (n = 0; n < loop->dimen; n++)
1056 dim = s->dim[n];
1058 /* Callee allocated arrays may not have a known bound yet. */
1059 if (loop->to[n])
1060 loop->to[n] = gfc_evaluate_now (
1061 fold_build2_loc (input_location, MINUS_EXPR,
1062 gfc_array_index_type,
1063 loop->to[n], loop->from[n]),
1064 pre);
1065 loop->from[n] = gfc_index_zero_node;
1067 /* We have just changed the loop bounds, we must clear the
1068 corresponding specloop, so that delta calculation is not skipped
1069 later in gfc_set_delta. */
1070 loop->specloop[n] = NULL;
1072 /* We are constructing the temporary's descriptor based on the loop
1073 dimensions. As the dimensions may be accessed in arbitrary order
1074 (think of transpose) the size taken from the n'th loop may not map
1075 to the n'th dimension of the array. We need to reconstruct loop
1076 infos in the right order before using it to set the descriptor
1077 bounds. */
1078 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1079 from[tmp_dim] = loop->from[n];
1080 to[tmp_dim] = loop->to[n];
1082 info->delta[dim] = gfc_index_zero_node;
1083 info->start[dim] = gfc_index_zero_node;
1084 info->end[dim] = gfc_index_zero_node;
1085 info->stride[dim] = gfc_index_one_node;
1089 /* Initialize the descriptor. */
1090 type =
1091 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1092 GFC_ARRAY_UNKNOWN, true);
1093 desc = gfc_create_var (type, "atmp");
1094 GFC_DECL_PACKED_ARRAY (desc) = 1;
1096 info->descriptor = desc;
1097 size = gfc_index_one_node;
1099 /* Fill in the array dtype. */
1100 tmp = gfc_conv_descriptor_dtype (desc);
1101 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1104 Fill in the bounds and stride. This is a packed array, so:
1106 size = 1;
1107 for (n = 0; n < rank; n++)
1109 stride[n] = size
1110 delta = ubound[n] + 1 - lbound[n];
1111 size = size * delta;
1113 size = size * sizeof(element);
1116 or_expr = NULL_TREE;
1118 /* If there is at least one null loop->to[n], it is a callee allocated
1119 array. */
1120 for (n = 0; n < total_dim; n++)
1121 if (to[n] == NULL_TREE)
1123 size = NULL_TREE;
1124 break;
1127 if (size == NULL_TREE)
1128 for (s = ss; s; s = s->parent)
1129 for (n = 0; n < s->loop->dimen; n++)
1131 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
1133 /* For a callee allocated array express the loop bounds in terms
1134 of the descriptor fields. */
1135 tmp = fold_build2_loc (input_location,
1136 MINUS_EXPR, gfc_array_index_type,
1137 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1138 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1139 s->loop->to[n] = tmp;
1141 else
1143 for (n = 0; n < total_dim; n++)
1145 /* Store the stride and bound components in the descriptor. */
1146 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1148 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1149 gfc_index_zero_node);
1151 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1153 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1154 gfc_array_index_type,
1155 to[n], gfc_index_one_node);
1157 /* Check whether the size for this dimension is negative. */
1158 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1159 tmp, gfc_index_zero_node);
1160 cond = gfc_evaluate_now (cond, pre);
1162 if (n == 0)
1163 or_expr = cond;
1164 else
1165 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1166 boolean_type_node, or_expr, cond);
1168 size = fold_build2_loc (input_location, MULT_EXPR,
1169 gfc_array_index_type, size, tmp);
1170 size = gfc_evaluate_now (size, pre);
1174 /* Get the size of the array. */
1175 if (size && !callee_alloc)
1177 tree elemsize;
1178 /* If or_expr is true, then the extent in at least one
1179 dimension is zero and the size is set to zero. */
1180 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1181 or_expr, gfc_index_zero_node, size);
1183 nelem = size;
1184 if (class_expr == NULL_TREE)
1185 elemsize = fold_convert (gfc_array_index_type,
1186 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1187 else
1188 elemsize = gfc_vtable_size_get (class_expr);
1190 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1191 size, elemsize);
1193 else
1195 nelem = size;
1196 size = NULL_TREE;
1199 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1200 dynamic, dealloc);
1202 while (ss->parent)
1203 ss = ss->parent;
1205 if (ss->dimen > ss->loop->temp_dim)
1206 ss->loop->temp_dim = ss->dimen;
1208 return size;
1212 /* Return the number of iterations in a loop that starts at START,
1213 ends at END, and has step STEP. */
1215 static tree
1216 gfc_get_iteration_count (tree start, tree end, tree step)
1218 tree tmp;
1219 tree type;
1221 type = TREE_TYPE (step);
1222 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1223 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1224 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1225 build_int_cst (type, 1));
1226 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1227 build_int_cst (type, 0));
1228 return fold_convert (gfc_array_index_type, tmp);
1232 /* Extend the data in array DESC by EXTRA elements. */
1234 static void
1235 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1237 tree arg0, arg1;
1238 tree tmp;
1239 tree size;
1240 tree ubound;
1242 if (integer_zerop (extra))
1243 return;
1245 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1247 /* Add EXTRA to the upper bound. */
1248 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1249 ubound, extra);
1250 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1252 /* Get the value of the current data pointer. */
1253 arg0 = gfc_conv_descriptor_data_get (desc);
1255 /* Calculate the new array size. */
1256 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1257 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1258 ubound, gfc_index_one_node);
1259 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1260 fold_convert (size_type_node, tmp),
1261 fold_convert (size_type_node, size));
1263 /* Call the realloc() function. */
1264 tmp = gfc_call_realloc (pblock, arg0, arg1);
1265 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1269 /* Return true if the bounds of iterator I can only be determined
1270 at run time. */
1272 static inline bool
1273 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1275 return (i->start->expr_type != EXPR_CONSTANT
1276 || i->end->expr_type != EXPR_CONSTANT
1277 || i->step->expr_type != EXPR_CONSTANT);
1281 /* Split the size of constructor element EXPR into the sum of two terms,
1282 one of which can be determined at compile time and one of which must
1283 be calculated at run time. Set *SIZE to the former and return true
1284 if the latter might be nonzero. */
1286 static bool
1287 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1289 if (expr->expr_type == EXPR_ARRAY)
1290 return gfc_get_array_constructor_size (size, expr->value.constructor);
1291 else if (expr->rank > 0)
1293 /* Calculate everything at run time. */
1294 mpz_set_ui (*size, 0);
1295 return true;
1297 else
1299 /* A single element. */
1300 mpz_set_ui (*size, 1);
1301 return false;
1306 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1307 of array constructor C. */
1309 static bool
1310 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1312 gfc_constructor *c;
1313 gfc_iterator *i;
1314 mpz_t val;
1315 mpz_t len;
1316 bool dynamic;
1318 mpz_set_ui (*size, 0);
1319 mpz_init (len);
1320 mpz_init (val);
1322 dynamic = false;
1323 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1325 i = c->iterator;
1326 if (i && gfc_iterator_has_dynamic_bounds (i))
1327 dynamic = true;
1328 else
1330 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1331 if (i)
1333 /* Multiply the static part of the element size by the
1334 number of iterations. */
1335 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1336 mpz_fdiv_q (val, val, i->step->value.integer);
1337 mpz_add_ui (val, val, 1);
1338 if (mpz_sgn (val) > 0)
1339 mpz_mul (len, len, val);
1340 else
1341 mpz_set_ui (len, 0);
1343 mpz_add (*size, *size, len);
1346 mpz_clear (len);
1347 mpz_clear (val);
1348 return dynamic;
1352 /* Make sure offset is a variable. */
1354 static void
1355 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1356 tree * offsetvar)
1358 /* We should have already created the offset variable. We cannot
1359 create it here because we may be in an inner scope. */
1360 gcc_assert (*offsetvar != NULL_TREE);
1361 gfc_add_modify (pblock, *offsetvar, *poffset);
1362 *poffset = *offsetvar;
1363 TREE_USED (*offsetvar) = 1;
1367 /* Variables needed for bounds-checking. */
1368 static bool first_len;
1369 static tree first_len_val;
1370 static bool typespec_chararray_ctor;
1372 static void
1373 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1374 tree offset, gfc_se * se, gfc_expr * expr)
1376 tree tmp;
1378 gfc_conv_expr (se, expr);
1380 /* Store the value. */
1381 tmp = build_fold_indirect_ref_loc (input_location,
1382 gfc_conv_descriptor_data_get (desc));
1383 tmp = gfc_build_array_ref (tmp, offset, NULL);
1385 if (expr->ts.type == BT_CHARACTER)
1387 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1388 tree esize;
1390 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1391 esize = fold_convert (gfc_charlen_type_node, esize);
1392 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1393 gfc_charlen_type_node, esize,
1394 build_int_cst (gfc_charlen_type_node,
1395 gfc_character_kinds[i].bit_size / 8));
1397 gfc_conv_string_parameter (se);
1398 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1400 /* The temporary is an array of pointers. */
1401 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1402 gfc_add_modify (&se->pre, tmp, se->expr);
1404 else
1406 /* The temporary is an array of string values. */
1407 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1408 /* We know the temporary and the value will be the same length,
1409 so can use memcpy. */
1410 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1411 se->string_length, se->expr, expr->ts.kind);
1413 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1415 if (first_len)
1417 gfc_add_modify (&se->pre, first_len_val,
1418 se->string_length);
1419 first_len = false;
1421 else
1423 /* Verify that all constructor elements are of the same
1424 length. */
1425 tree cond = fold_build2_loc (input_location, NE_EXPR,
1426 boolean_type_node, first_len_val,
1427 se->string_length);
1428 gfc_trans_runtime_check
1429 (true, false, cond, &se->pre, &expr->where,
1430 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1431 fold_convert (long_integer_type_node, first_len_val),
1432 fold_convert (long_integer_type_node, se->string_length));
1436 else
1438 /* TODO: Should the frontend already have done this conversion? */
1439 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1440 gfc_add_modify (&se->pre, tmp, se->expr);
1443 gfc_add_block_to_block (pblock, &se->pre);
1444 gfc_add_block_to_block (pblock, &se->post);
1448 /* Add the contents of an array to the constructor. DYNAMIC is as for
1449 gfc_trans_array_constructor_value. */
1451 static void
1452 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1453 tree type ATTRIBUTE_UNUSED,
1454 tree desc, gfc_expr * expr,
1455 tree * poffset, tree * offsetvar,
1456 bool dynamic)
1458 gfc_se se;
1459 gfc_ss *ss;
1460 gfc_loopinfo loop;
1461 stmtblock_t body;
1462 tree tmp;
1463 tree size;
1464 int n;
1466 /* We need this to be a variable so we can increment it. */
1467 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1469 gfc_init_se (&se, NULL);
1471 /* Walk the array expression. */
1472 ss = gfc_walk_expr (expr);
1473 gcc_assert (ss != gfc_ss_terminator);
1475 /* Initialize the scalarizer. */
1476 gfc_init_loopinfo (&loop);
1477 gfc_add_ss_to_loop (&loop, ss);
1479 /* Initialize the loop. */
1480 gfc_conv_ss_startstride (&loop);
1481 gfc_conv_loop_setup (&loop, &expr->where);
1483 /* Make sure the constructed array has room for the new data. */
1484 if (dynamic)
1486 /* Set SIZE to the total number of elements in the subarray. */
1487 size = gfc_index_one_node;
1488 for (n = 0; n < loop.dimen; n++)
1490 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1491 gfc_index_one_node);
1492 size = fold_build2_loc (input_location, MULT_EXPR,
1493 gfc_array_index_type, size, tmp);
1496 /* Grow the constructed array by SIZE elements. */
1497 gfc_grow_array (&loop.pre, desc, size);
1500 /* Make the loop body. */
1501 gfc_mark_ss_chain_used (ss, 1);
1502 gfc_start_scalarized_body (&loop, &body);
1503 gfc_copy_loopinfo_to_se (&se, &loop);
1504 se.ss = ss;
1506 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1507 gcc_assert (se.ss == gfc_ss_terminator);
1509 /* Increment the offset. */
1510 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1511 *poffset, gfc_index_one_node);
1512 gfc_add_modify (&body, *poffset, tmp);
1514 /* Finish the loop. */
1515 gfc_trans_scalarizing_loops (&loop, &body);
1516 gfc_add_block_to_block (&loop.pre, &loop.post);
1517 tmp = gfc_finish_block (&loop.pre);
1518 gfc_add_expr_to_block (pblock, tmp);
1520 gfc_cleanup_loop (&loop);
1524 /* Assign the values to the elements of an array constructor. DYNAMIC
1525 is true if descriptor DESC only contains enough data for the static
1526 size calculated by gfc_get_array_constructor_size. When true, memory
1527 for the dynamic parts must be allocated using realloc. */
1529 static void
1530 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1531 tree desc, gfc_constructor_base base,
1532 tree * poffset, tree * offsetvar,
1533 bool dynamic)
1535 tree tmp;
1536 tree start = NULL_TREE;
1537 tree end = NULL_TREE;
1538 tree step = NULL_TREE;
1539 stmtblock_t body;
1540 gfc_se se;
1541 mpz_t size;
1542 gfc_constructor *c;
1544 tree shadow_loopvar = NULL_TREE;
1545 gfc_saved_var saved_loopvar;
1547 mpz_init (size);
1548 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1550 /* If this is an iterator or an array, the offset must be a variable. */
1551 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1552 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1554 /* Shadowing the iterator avoids changing its value and saves us from
1555 keeping track of it. Further, it makes sure that there's always a
1556 backend-decl for the symbol, even if there wasn't one before,
1557 e.g. in the case of an iterator that appears in a specification
1558 expression in an interface mapping. */
1559 if (c->iterator)
1561 gfc_symbol *sym;
1562 tree type;
1564 /* Evaluate loop bounds before substituting the loop variable
1565 in case they depend on it. Such a case is invalid, but it is
1566 not more expensive to do the right thing here.
1567 See PR 44354. */
1568 gfc_init_se (&se, NULL);
1569 gfc_conv_expr_val (&se, c->iterator->start);
1570 gfc_add_block_to_block (pblock, &se.pre);
1571 start = gfc_evaluate_now (se.expr, pblock);
1573 gfc_init_se (&se, NULL);
1574 gfc_conv_expr_val (&se, c->iterator->end);
1575 gfc_add_block_to_block (pblock, &se.pre);
1576 end = gfc_evaluate_now (se.expr, pblock);
1578 gfc_init_se (&se, NULL);
1579 gfc_conv_expr_val (&se, c->iterator->step);
1580 gfc_add_block_to_block (pblock, &se.pre);
1581 step = gfc_evaluate_now (se.expr, pblock);
1583 sym = c->iterator->var->symtree->n.sym;
1584 type = gfc_typenode_for_spec (&sym->ts);
1586 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1587 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1590 gfc_start_block (&body);
1592 if (c->expr->expr_type == EXPR_ARRAY)
1594 /* Array constructors can be nested. */
1595 gfc_trans_array_constructor_value (&body, type, desc,
1596 c->expr->value.constructor,
1597 poffset, offsetvar, dynamic);
1599 else if (c->expr->rank > 0)
1601 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1602 poffset, offsetvar, dynamic);
1604 else
1606 /* This code really upsets the gimplifier so don't bother for now. */
1607 gfc_constructor *p;
1608 HOST_WIDE_INT n;
1609 HOST_WIDE_INT size;
1611 p = c;
1612 n = 0;
1613 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1615 p = gfc_constructor_next (p);
1616 n++;
1618 if (n < 4)
1620 /* Scalar values. */
1621 gfc_init_se (&se, NULL);
1622 gfc_trans_array_ctor_element (&body, desc, *poffset,
1623 &se, c->expr);
1625 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1626 gfc_array_index_type,
1627 *poffset, gfc_index_one_node);
1629 else
1631 /* Collect multiple scalar constants into a constructor. */
1632 vec<constructor_elt, va_gc> *v = NULL;
1633 tree init;
1634 tree bound;
1635 tree tmptype;
1636 HOST_WIDE_INT idx = 0;
1638 p = c;
1639 /* Count the number of consecutive scalar constants. */
1640 while (p && !(p->iterator
1641 || p->expr->expr_type != EXPR_CONSTANT))
1643 gfc_init_se (&se, NULL);
1644 gfc_conv_constant (&se, p->expr);
1646 if (c->expr->ts.type != BT_CHARACTER)
1647 se.expr = fold_convert (type, se.expr);
1648 /* For constant character array constructors we build
1649 an array of pointers. */
1650 else if (POINTER_TYPE_P (type))
1651 se.expr = gfc_build_addr_expr
1652 (gfc_get_pchar_type (p->expr->ts.kind),
1653 se.expr);
1655 CONSTRUCTOR_APPEND_ELT (v,
1656 build_int_cst (gfc_array_index_type,
1657 idx++),
1658 se.expr);
1659 c = p;
1660 p = gfc_constructor_next (p);
1663 bound = size_int (n - 1);
1664 /* Create an array type to hold them. */
1665 tmptype = build_range_type (gfc_array_index_type,
1666 gfc_index_zero_node, bound);
1667 tmptype = build_array_type (type, tmptype);
1669 init = build_constructor (tmptype, v);
1670 TREE_CONSTANT (init) = 1;
1671 TREE_STATIC (init) = 1;
1672 /* Create a static variable to hold the data. */
1673 tmp = gfc_create_var (tmptype, "data");
1674 TREE_STATIC (tmp) = 1;
1675 TREE_CONSTANT (tmp) = 1;
1676 TREE_READONLY (tmp) = 1;
1677 DECL_INITIAL (tmp) = init;
1678 init = tmp;
1680 /* Use BUILTIN_MEMCPY to assign the values. */
1681 tmp = gfc_conv_descriptor_data_get (desc);
1682 tmp = build_fold_indirect_ref_loc (input_location,
1683 tmp);
1684 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1685 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1686 init = gfc_build_addr_expr (NULL_TREE, init);
1688 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1689 bound = build_int_cst (size_type_node, n * size);
1690 tmp = build_call_expr_loc (input_location,
1691 builtin_decl_explicit (BUILT_IN_MEMCPY),
1692 3, tmp, init, bound);
1693 gfc_add_expr_to_block (&body, tmp);
1695 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1696 gfc_array_index_type, *poffset,
1697 build_int_cst (gfc_array_index_type, n));
1699 if (!INTEGER_CST_P (*poffset))
1701 gfc_add_modify (&body, *offsetvar, *poffset);
1702 *poffset = *offsetvar;
1706 /* The frontend should already have done any expansions
1707 at compile-time. */
1708 if (!c->iterator)
1710 /* Pass the code as is. */
1711 tmp = gfc_finish_block (&body);
1712 gfc_add_expr_to_block (pblock, tmp);
1714 else
1716 /* Build the implied do-loop. */
1717 stmtblock_t implied_do_block;
1718 tree cond;
1719 tree exit_label;
1720 tree loopbody;
1721 tree tmp2;
1723 loopbody = gfc_finish_block (&body);
1725 /* Create a new block that holds the implied-do loop. A temporary
1726 loop-variable is used. */
1727 gfc_start_block(&implied_do_block);
1729 /* Initialize the loop. */
1730 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
1732 /* If this array expands dynamically, and the number of iterations
1733 is not constant, we won't have allocated space for the static
1734 part of C->EXPR's size. Do that now. */
1735 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1737 /* Get the number of iterations. */
1738 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1740 /* Get the static part of C->EXPR's size. */
1741 gfc_get_array_constructor_element_size (&size, c->expr);
1742 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1744 /* Grow the array by TMP * TMP2 elements. */
1745 tmp = fold_build2_loc (input_location, MULT_EXPR,
1746 gfc_array_index_type, tmp, tmp2);
1747 gfc_grow_array (&implied_do_block, desc, tmp);
1750 /* Generate the loop body. */
1751 exit_label = gfc_build_label_decl (NULL_TREE);
1752 gfc_start_block (&body);
1754 /* Generate the exit condition. Depending on the sign of
1755 the step variable we have to generate the correct
1756 comparison. */
1757 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1758 step, build_int_cst (TREE_TYPE (step), 0));
1759 cond = fold_build3_loc (input_location, COND_EXPR,
1760 boolean_type_node, tmp,
1761 fold_build2_loc (input_location, GT_EXPR,
1762 boolean_type_node, shadow_loopvar, end),
1763 fold_build2_loc (input_location, LT_EXPR,
1764 boolean_type_node, shadow_loopvar, end));
1765 tmp = build1_v (GOTO_EXPR, exit_label);
1766 TREE_USED (exit_label) = 1;
1767 tmp = build3_v (COND_EXPR, cond, tmp,
1768 build_empty_stmt (input_location));
1769 gfc_add_expr_to_block (&body, tmp);
1771 /* The main loop body. */
1772 gfc_add_expr_to_block (&body, loopbody);
1774 /* Increase loop variable by step. */
1775 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1776 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1777 step);
1778 gfc_add_modify (&body, shadow_loopvar, tmp);
1780 /* Finish the loop. */
1781 tmp = gfc_finish_block (&body);
1782 tmp = build1_v (LOOP_EXPR, tmp);
1783 gfc_add_expr_to_block (&implied_do_block, tmp);
1785 /* Add the exit label. */
1786 tmp = build1_v (LABEL_EXPR, exit_label);
1787 gfc_add_expr_to_block (&implied_do_block, tmp);
1789 /* Finish the implied-do loop. */
1790 tmp = gfc_finish_block(&implied_do_block);
1791 gfc_add_expr_to_block(pblock, tmp);
1793 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1796 mpz_clear (size);
1800 /* A catch-all to obtain the string length for anything that is not
1801 a substring of non-constant length, a constant, array or variable. */
1803 static void
1804 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1806 gfc_se se;
1808 /* Don't bother if we already know the length is a constant. */
1809 if (*len && INTEGER_CST_P (*len))
1810 return;
1812 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1813 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1815 /* This is easy. */
1816 gfc_conv_const_charlen (e->ts.u.cl);
1817 *len = e->ts.u.cl->backend_decl;
1819 else
1821 /* Otherwise, be brutal even if inefficient. */
1822 gfc_init_se (&se, NULL);
1824 /* No function call, in case of side effects. */
1825 se.no_function_call = 1;
1826 if (e->rank == 0)
1827 gfc_conv_expr (&se, e);
1828 else
1829 gfc_conv_expr_descriptor (&se, e);
1831 /* Fix the value. */
1832 *len = gfc_evaluate_now (se.string_length, &se.pre);
1834 gfc_add_block_to_block (block, &se.pre);
1835 gfc_add_block_to_block (block, &se.post);
1837 e->ts.u.cl->backend_decl = *len;
1842 /* Figure out the string length of a variable reference expression.
1843 Used by get_array_ctor_strlen. */
1845 static void
1846 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
1848 gfc_ref *ref;
1849 gfc_typespec *ts;
1850 mpz_t char_len;
1852 /* Don't bother if we already know the length is a constant. */
1853 if (*len && INTEGER_CST_P (*len))
1854 return;
1856 ts = &expr->symtree->n.sym->ts;
1857 for (ref = expr->ref; ref; ref = ref->next)
1859 switch (ref->type)
1861 case REF_ARRAY:
1862 /* Array references don't change the string length. */
1863 break;
1865 case REF_COMPONENT:
1866 /* Use the length of the component. */
1867 ts = &ref->u.c.component->ts;
1868 break;
1870 case REF_SUBSTRING:
1871 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1872 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1874 /* Note that this might evaluate expr. */
1875 get_array_ctor_all_strlen (block, expr, len);
1876 return;
1878 mpz_init_set_ui (char_len, 1);
1879 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1880 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1881 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1882 *len = convert (gfc_charlen_type_node, *len);
1883 mpz_clear (char_len);
1884 return;
1886 default:
1887 gcc_unreachable ();
1891 *len = ts->u.cl->backend_decl;
1895 /* Figure out the string length of a character array constructor.
1896 If len is NULL, don't calculate the length; this happens for recursive calls
1897 when a sub-array-constructor is an element but not at the first position,
1898 so when we're not interested in the length.
1899 Returns TRUE if all elements are character constants. */
1901 bool
1902 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
1904 gfc_constructor *c;
1905 bool is_const;
1907 is_const = TRUE;
1909 if (gfc_constructor_first (base) == NULL)
1911 if (len)
1912 *len = build_int_cstu (gfc_charlen_type_node, 0);
1913 return is_const;
1916 /* Loop over all constructor elements to find out is_const, but in len we
1917 want to store the length of the first, not the last, element. We can
1918 of course exit the loop as soon as is_const is found to be false. */
1919 for (c = gfc_constructor_first (base);
1920 c && is_const; c = gfc_constructor_next (c))
1922 switch (c->expr->expr_type)
1924 case EXPR_CONSTANT:
1925 if (len && !(*len && INTEGER_CST_P (*len)))
1926 *len = build_int_cstu (gfc_charlen_type_node,
1927 c->expr->value.character.length);
1928 break;
1930 case EXPR_ARRAY:
1931 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1932 is_const = false;
1933 break;
1935 case EXPR_VARIABLE:
1936 is_const = false;
1937 if (len)
1938 get_array_ctor_var_strlen (block, c->expr, len);
1939 break;
1941 default:
1942 is_const = false;
1943 if (len)
1944 get_array_ctor_all_strlen (block, c->expr, len);
1945 break;
1948 /* After the first iteration, we don't want the length modified. */
1949 len = NULL;
1952 return is_const;
1955 /* Check whether the array constructor C consists entirely of constant
1956 elements, and if so returns the number of those elements, otherwise
1957 return zero. Note, an empty or NULL array constructor returns zero. */
1959 unsigned HOST_WIDE_INT
1960 gfc_constant_array_constructor_p (gfc_constructor_base base)
1962 unsigned HOST_WIDE_INT nelem = 0;
1964 gfc_constructor *c = gfc_constructor_first (base);
1965 while (c)
1967 if (c->iterator
1968 || c->expr->rank > 0
1969 || c->expr->expr_type != EXPR_CONSTANT)
1970 return 0;
1971 c = gfc_constructor_next (c);
1972 nelem++;
1974 return nelem;
1978 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1979 and the tree type of it's elements, TYPE, return a static constant
1980 variable that is compile-time initialized. */
1982 tree
1983 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1985 tree tmptype, init, tmp;
1986 HOST_WIDE_INT nelem;
1987 gfc_constructor *c;
1988 gfc_array_spec as;
1989 gfc_se se;
1990 int i;
1991 vec<constructor_elt, va_gc> *v = NULL;
1993 /* First traverse the constructor list, converting the constants
1994 to tree to build an initializer. */
1995 nelem = 0;
1996 c = gfc_constructor_first (expr->value.constructor);
1997 while (c)
1999 gfc_init_se (&se, NULL);
2000 gfc_conv_constant (&se, c->expr);
2001 if (c->expr->ts.type != BT_CHARACTER)
2002 se.expr = fold_convert (type, se.expr);
2003 else if (POINTER_TYPE_P (type))
2004 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2005 se.expr);
2006 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2007 se.expr);
2008 c = gfc_constructor_next (c);
2009 nelem++;
2012 /* Next determine the tree type for the array. We use the gfortran
2013 front-end's gfc_get_nodesc_array_type in order to create a suitable
2014 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2016 memset (&as, 0, sizeof (gfc_array_spec));
2018 as.rank = expr->rank;
2019 as.type = AS_EXPLICIT;
2020 if (!expr->shape)
2022 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2023 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2024 NULL, nelem - 1);
2026 else
2027 for (i = 0; i < expr->rank; i++)
2029 int tmp = (int) mpz_get_si (expr->shape[i]);
2030 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2031 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2032 NULL, tmp - 1);
2035 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
2037 /* as is not needed anymore. */
2038 for (i = 0; i < as.rank + as.corank; i++)
2040 gfc_free_expr (as.lower[i]);
2041 gfc_free_expr (as.upper[i]);
2044 init = build_constructor (tmptype, v);
2046 TREE_CONSTANT (init) = 1;
2047 TREE_STATIC (init) = 1;
2049 tmp = build_decl (input_location, VAR_DECL, create_tmp_var_name ("A"),
2050 tmptype);
2051 DECL_ARTIFICIAL (tmp) = 1;
2052 DECL_IGNORED_P (tmp) = 1;
2053 TREE_STATIC (tmp) = 1;
2054 TREE_CONSTANT (tmp) = 1;
2055 TREE_READONLY (tmp) = 1;
2056 DECL_INITIAL (tmp) = init;
2057 pushdecl (tmp);
2059 return tmp;
2063 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2064 This mostly initializes the scalarizer state info structure with the
2065 appropriate values to directly use the array created by the function
2066 gfc_build_constant_array_constructor. */
2068 static void
2069 trans_constant_array_constructor (gfc_ss * ss, tree type)
2071 gfc_array_info *info;
2072 tree tmp;
2073 int i;
2075 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
2077 info = &ss->info->data.array;
2079 info->descriptor = tmp;
2080 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
2081 info->offset = gfc_index_zero_node;
2083 for (i = 0; i < ss->dimen; i++)
2085 info->delta[i] = gfc_index_zero_node;
2086 info->start[i] = gfc_index_zero_node;
2087 info->end[i] = gfc_index_zero_node;
2088 info->stride[i] = gfc_index_one_node;
2093 static int
2094 get_rank (gfc_loopinfo *loop)
2096 int rank;
2098 rank = 0;
2099 for (; loop; loop = loop->parent)
2100 rank += loop->dimen;
2102 return rank;
2106 /* Helper routine of gfc_trans_array_constructor to determine if the
2107 bounds of the loop specified by LOOP are constant and simple enough
2108 to use with trans_constant_array_constructor. Returns the
2109 iteration count of the loop if suitable, and NULL_TREE otherwise. */
2111 static tree
2112 constant_array_constructor_loop_size (gfc_loopinfo * l)
2114 gfc_loopinfo *loop;
2115 tree size = gfc_index_one_node;
2116 tree tmp;
2117 int i, total_dim;
2119 total_dim = get_rank (l);
2121 for (loop = l; loop; loop = loop->parent)
2123 for (i = 0; i < loop->dimen; i++)
2125 /* If the bounds aren't constant, return NULL_TREE. */
2126 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2127 return NULL_TREE;
2128 if (!integer_zerop (loop->from[i]))
2130 /* Only allow nonzero "from" in one-dimensional arrays. */
2131 if (total_dim != 1)
2132 return NULL_TREE;
2133 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2134 gfc_array_index_type,
2135 loop->to[i], loop->from[i]);
2137 else
2138 tmp = loop->to[i];
2139 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2140 gfc_array_index_type, tmp, gfc_index_one_node);
2141 size = fold_build2_loc (input_location, MULT_EXPR,
2142 gfc_array_index_type, size, tmp);
2146 return size;
2150 static tree *
2151 get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2153 gfc_ss *ss;
2154 int n;
2156 gcc_assert (array->nested_ss == NULL);
2158 for (ss = array; ss; ss = ss->parent)
2159 for (n = 0; n < ss->loop->dimen; n++)
2160 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2161 return &(ss->loop->to[n]);
2163 gcc_unreachable ();
2167 static gfc_loopinfo *
2168 outermost_loop (gfc_loopinfo * loop)
2170 while (loop->parent != NULL)
2171 loop = loop->parent;
2173 return loop;
2177 /* Array constructors are handled by constructing a temporary, then using that
2178 within the scalarization loop. This is not optimal, but seems by far the
2179 simplest method. */
2181 static void
2182 trans_array_constructor (gfc_ss * ss, locus * where)
2184 gfc_constructor_base c;
2185 tree offset;
2186 tree offsetvar;
2187 tree desc;
2188 tree type;
2189 tree tmp;
2190 tree *loop_ubound0;
2191 bool dynamic;
2192 bool old_first_len, old_typespec_chararray_ctor;
2193 tree old_first_len_val;
2194 gfc_loopinfo *loop, *outer_loop;
2195 gfc_ss_info *ss_info;
2196 gfc_expr *expr;
2197 gfc_ss *s;
2199 /* Save the old values for nested checking. */
2200 old_first_len = first_len;
2201 old_first_len_val = first_len_val;
2202 old_typespec_chararray_ctor = typespec_chararray_ctor;
2204 loop = ss->loop;
2205 outer_loop = outermost_loop (loop);
2206 ss_info = ss->info;
2207 expr = ss_info->expr;
2209 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2210 typespec was given for the array constructor. */
2211 typespec_chararray_ctor = (expr->ts.u.cl
2212 && expr->ts.u.cl->length_from_typespec);
2214 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2215 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2217 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2218 first_len = true;
2221 gcc_assert (ss->dimen == ss->loop->dimen);
2223 c = expr->value.constructor;
2224 if (expr->ts.type == BT_CHARACTER)
2226 bool const_string;
2228 /* get_array_ctor_strlen walks the elements of the constructor, if a
2229 typespec was given, we already know the string length and want the one
2230 specified there. */
2231 if (typespec_chararray_ctor && expr->ts.u.cl->length
2232 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2234 gfc_se length_se;
2236 const_string = false;
2237 gfc_init_se (&length_se, NULL);
2238 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2239 gfc_charlen_type_node);
2240 ss_info->string_length = length_se.expr;
2241 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2242 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2244 else
2245 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2246 &ss_info->string_length);
2248 /* Complex character array constructors should have been taken care of
2249 and not end up here. */
2250 gcc_assert (ss_info->string_length);
2252 expr->ts.u.cl->backend_decl = ss_info->string_length;
2254 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2255 if (const_string)
2256 type = build_pointer_type (type);
2258 else
2259 type = gfc_typenode_for_spec (&expr->ts);
2261 /* See if the constructor determines the loop bounds. */
2262 dynamic = false;
2264 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2266 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
2268 /* We have a multidimensional parameter. */
2269 for (s = ss; s; s = s->parent)
2271 int n;
2272 for (n = 0; n < s->loop->dimen; n++)
2274 s->loop->from[n] = gfc_index_zero_node;
2275 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2276 gfc_index_integer_kind);
2277 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2278 gfc_array_index_type,
2279 s->loop->to[n],
2280 gfc_index_one_node);
2285 if (*loop_ubound0 == NULL_TREE)
2287 mpz_t size;
2289 /* We should have a 1-dimensional, zero-based loop. */
2290 gcc_assert (loop->parent == NULL && loop->nested == NULL);
2291 gcc_assert (loop->dimen == 1);
2292 gcc_assert (integer_zerop (loop->from[0]));
2294 /* Split the constructor size into a static part and a dynamic part.
2295 Allocate the static size up-front and record whether the dynamic
2296 size might be nonzero. */
2297 mpz_init (size);
2298 dynamic = gfc_get_array_constructor_size (&size, c);
2299 mpz_sub_ui (size, size, 1);
2300 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2301 mpz_clear (size);
2304 /* Special case constant array constructors. */
2305 if (!dynamic)
2307 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2308 if (nelem > 0)
2310 tree size = constant_array_constructor_loop_size (loop);
2311 if (size && compare_tree_int (size, nelem) == 0)
2313 trans_constant_array_constructor (ss, type);
2314 goto finish;
2319 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2320 NULL_TREE, dynamic, true, false, where);
2322 desc = ss_info->data.array.descriptor;
2323 offset = gfc_index_zero_node;
2324 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2325 TREE_NO_WARNING (offsetvar) = 1;
2326 TREE_USED (offsetvar) = 0;
2327 gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
2328 &offset, &offsetvar, dynamic);
2330 /* If the array grows dynamically, the upper bound of the loop variable
2331 is determined by the array's final upper bound. */
2332 if (dynamic)
2334 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2335 gfc_array_index_type,
2336 offsetvar, gfc_index_one_node);
2337 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2338 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2339 if (*loop_ubound0 && TREE_CODE (*loop_ubound0) == VAR_DECL)
2340 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
2341 else
2342 *loop_ubound0 = tmp;
2345 if (TREE_USED (offsetvar))
2346 pushdecl (offsetvar);
2347 else
2348 gcc_assert (INTEGER_CST_P (offset));
2350 #if 0
2351 /* Disable bound checking for now because it's probably broken. */
2352 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2354 gcc_unreachable ();
2356 #endif
2358 finish:
2359 /* Restore old values of globals. */
2360 first_len = old_first_len;
2361 first_len_val = old_first_len_val;
2362 typespec_chararray_ctor = old_typespec_chararray_ctor;
2366 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2367 called after evaluating all of INFO's vector dimensions. Go through
2368 each such vector dimension and see if we can now fill in any missing
2369 loop bounds. */
2371 static void
2372 set_vector_loop_bounds (gfc_ss * ss)
2374 gfc_loopinfo *loop, *outer_loop;
2375 gfc_array_info *info;
2376 gfc_se se;
2377 tree tmp;
2378 tree desc;
2379 tree zero;
2380 int n;
2381 int dim;
2383 outer_loop = outermost_loop (ss->loop);
2385 info = &ss->info->data.array;
2387 for (; ss; ss = ss->parent)
2389 loop = ss->loop;
2391 for (n = 0; n < loop->dimen; n++)
2393 dim = ss->dim[n];
2394 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2395 || loop->to[n] != NULL)
2396 continue;
2398 /* Loop variable N indexes vector dimension DIM, and we don't
2399 yet know the upper bound of loop variable N. Set it to the
2400 difference between the vector's upper and lower bounds. */
2401 gcc_assert (loop->from[n] == gfc_index_zero_node);
2402 gcc_assert (info->subscript[dim]
2403 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2405 gfc_init_se (&se, NULL);
2406 desc = info->subscript[dim]->info->data.array.descriptor;
2407 zero = gfc_rank_cst[0];
2408 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2409 gfc_array_index_type,
2410 gfc_conv_descriptor_ubound_get (desc, zero),
2411 gfc_conv_descriptor_lbound_get (desc, zero));
2412 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2413 loop->to[n] = tmp;
2419 /* Add the pre and post chains for all the scalar expressions in a SS chain
2420 to loop. This is called after the loop parameters have been calculated,
2421 but before the actual scalarizing loops. */
2423 static void
2424 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2425 locus * where)
2427 gfc_loopinfo *nested_loop, *outer_loop;
2428 gfc_se se;
2429 gfc_ss_info *ss_info;
2430 gfc_array_info *info;
2431 gfc_expr *expr;
2432 int n;
2434 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
2435 arguments could get evaluated multiple times. */
2436 if (ss->is_alloc_lhs)
2437 return;
2439 outer_loop = outermost_loop (loop);
2441 /* TODO: This can generate bad code if there are ordering dependencies,
2442 e.g., a callee allocated function and an unknown size constructor. */
2443 gcc_assert (ss != NULL);
2445 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2447 gcc_assert (ss);
2449 /* Cross loop arrays are handled from within the most nested loop. */
2450 if (ss->nested_ss != NULL)
2451 continue;
2453 ss_info = ss->info;
2454 expr = ss_info->expr;
2455 info = &ss_info->data.array;
2457 switch (ss_info->type)
2459 case GFC_SS_SCALAR:
2460 /* Scalar expression. Evaluate this now. This includes elemental
2461 dimension indices, but not array section bounds. */
2462 gfc_init_se (&se, NULL);
2463 gfc_conv_expr (&se, expr);
2464 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2466 if (expr->ts.type != BT_CHARACTER)
2468 /* Move the evaluation of scalar expressions outside the
2469 scalarization loop, except for WHERE assignments. */
2470 if (subscript)
2471 se.expr = convert(gfc_array_index_type, se.expr);
2472 if (!ss_info->where)
2473 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
2474 gfc_add_block_to_block (&outer_loop->pre, &se.post);
2476 else
2477 gfc_add_block_to_block (&outer_loop->post, &se.post);
2479 ss_info->data.scalar.value = se.expr;
2480 ss_info->string_length = se.string_length;
2481 break;
2483 case GFC_SS_REFERENCE:
2484 /* Scalar argument to elemental procedure. */
2485 gfc_init_se (&se, NULL);
2486 if (ss_info->can_be_null_ref)
2488 /* If the actual argument can be absent (in other words, it can
2489 be a NULL reference), don't try to evaluate it; pass instead
2490 the reference directly. */
2491 gfc_conv_expr_reference (&se, expr);
2493 else
2495 /* Otherwise, evaluate the argument outside the loop and pass
2496 a reference to the value. */
2497 gfc_conv_expr (&se, expr);
2500 /* Ensure that a pointer to the string is stored. */
2501 if (expr->ts.type == BT_CHARACTER)
2502 gfc_conv_string_parameter (&se);
2504 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2505 gfc_add_block_to_block (&outer_loop->post, &se.post);
2506 if (gfc_is_class_scalar_expr (expr))
2507 /* This is necessary because the dynamic type will always be
2508 large than the declared type. In consequence, assigning
2509 the value to a temporary could segfault.
2510 OOP-TODO: see if this is generally correct or is the value
2511 has to be written to an allocated temporary, whose address
2512 is passed via ss_info. */
2513 ss_info->data.scalar.value = se.expr;
2514 else
2515 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
2516 &outer_loop->pre);
2518 ss_info->string_length = se.string_length;
2519 break;
2521 case GFC_SS_SECTION:
2522 /* Add the expressions for scalar and vector subscripts. */
2523 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2524 if (info->subscript[n])
2525 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2527 set_vector_loop_bounds (ss);
2528 break;
2530 case GFC_SS_VECTOR:
2531 /* Get the vector's descriptor and store it in SS. */
2532 gfc_init_se (&se, NULL);
2533 gfc_conv_expr_descriptor (&se, expr);
2534 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2535 gfc_add_block_to_block (&outer_loop->post, &se.post);
2536 info->descriptor = se.expr;
2537 break;
2539 case GFC_SS_INTRINSIC:
2540 gfc_add_intrinsic_ss_code (loop, ss);
2541 break;
2543 case GFC_SS_FUNCTION:
2544 /* Array function return value. We call the function and save its
2545 result in a temporary for use inside the loop. */
2546 gfc_init_se (&se, NULL);
2547 se.loop = loop;
2548 se.ss = ss;
2549 gfc_conv_expr (&se, expr);
2550 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2551 gfc_add_block_to_block (&outer_loop->post, &se.post);
2552 ss_info->string_length = se.string_length;
2553 break;
2555 case GFC_SS_CONSTRUCTOR:
2556 if (expr->ts.type == BT_CHARACTER
2557 && ss_info->string_length == NULL
2558 && expr->ts.u.cl
2559 && expr->ts.u.cl->length)
2561 gfc_init_se (&se, NULL);
2562 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2563 gfc_charlen_type_node);
2564 ss_info->string_length = se.expr;
2565 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2566 gfc_add_block_to_block (&outer_loop->post, &se.post);
2568 trans_array_constructor (ss, where);
2569 break;
2571 case GFC_SS_TEMP:
2572 case GFC_SS_COMPONENT:
2573 /* Do nothing. These are handled elsewhere. */
2574 break;
2576 default:
2577 gcc_unreachable ();
2581 if (!subscript)
2582 for (nested_loop = loop->nested; nested_loop;
2583 nested_loop = nested_loop->next)
2584 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
2588 /* Translate expressions for the descriptor and data pointer of a SS. */
2589 /*GCC ARRAYS*/
2591 static void
2592 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2594 gfc_se se;
2595 gfc_ss_info *ss_info;
2596 gfc_array_info *info;
2597 tree tmp;
2599 ss_info = ss->info;
2600 info = &ss_info->data.array;
2602 /* Get the descriptor for the array to be scalarized. */
2603 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2604 gfc_init_se (&se, NULL);
2605 se.descriptor_only = 1;
2606 gfc_conv_expr_lhs (&se, ss_info->expr);
2607 gfc_add_block_to_block (block, &se.pre);
2608 info->descriptor = se.expr;
2609 ss_info->string_length = se.string_length;
2611 if (base)
2613 /* Also the data pointer. */
2614 tmp = gfc_conv_array_data (se.expr);
2615 /* If this is a variable or address of a variable we use it directly.
2616 Otherwise we must evaluate it now to avoid breaking dependency
2617 analysis by pulling the expressions for elemental array indices
2618 inside the loop. */
2619 if (!(DECL_P (tmp)
2620 || (TREE_CODE (tmp) == ADDR_EXPR
2621 && DECL_P (TREE_OPERAND (tmp, 0)))))
2622 tmp = gfc_evaluate_now (tmp, block);
2623 info->data = tmp;
2625 tmp = gfc_conv_array_offset (se.expr);
2626 info->offset = gfc_evaluate_now (tmp, block);
2628 /* Make absolutely sure that the saved_offset is indeed saved
2629 so that the variable is still accessible after the loops
2630 are translated. */
2631 info->saved_offset = info->offset;
2636 /* Initialize a gfc_loopinfo structure. */
2638 void
2639 gfc_init_loopinfo (gfc_loopinfo * loop)
2641 int n;
2643 memset (loop, 0, sizeof (gfc_loopinfo));
2644 gfc_init_block (&loop->pre);
2645 gfc_init_block (&loop->post);
2647 /* Initially scalarize in order and default to no loop reversal. */
2648 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2650 loop->order[n] = n;
2651 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2654 loop->ss = gfc_ss_terminator;
2658 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2659 chain. */
2661 void
2662 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2664 se->loop = loop;
2668 /* Return an expression for the data pointer of an array. */
2670 tree
2671 gfc_conv_array_data (tree descriptor)
2673 tree type;
2675 type = TREE_TYPE (descriptor);
2676 if (GFC_ARRAY_TYPE_P (type))
2678 if (TREE_CODE (type) == POINTER_TYPE)
2679 return descriptor;
2680 else
2682 /* Descriptorless arrays. */
2683 return gfc_build_addr_expr (NULL_TREE, descriptor);
2686 else
2687 return gfc_conv_descriptor_data_get (descriptor);
2691 /* Return an expression for the base offset of an array. */
2693 tree
2694 gfc_conv_array_offset (tree descriptor)
2696 tree type;
2698 type = TREE_TYPE (descriptor);
2699 if (GFC_ARRAY_TYPE_P (type))
2700 return GFC_TYPE_ARRAY_OFFSET (type);
2701 else
2702 return gfc_conv_descriptor_offset_get (descriptor);
2706 /* Get an expression for the array stride. */
2708 tree
2709 gfc_conv_array_stride (tree descriptor, int dim)
2711 tree tmp;
2712 tree type;
2714 type = TREE_TYPE (descriptor);
2716 /* For descriptorless arrays use the array size. */
2717 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2718 if (tmp != NULL_TREE)
2719 return tmp;
2721 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2722 return tmp;
2726 /* Like gfc_conv_array_stride, but for the lower bound. */
2728 tree
2729 gfc_conv_array_lbound (tree descriptor, int dim)
2731 tree tmp;
2732 tree type;
2734 type = TREE_TYPE (descriptor);
2736 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2737 if (tmp != NULL_TREE)
2738 return tmp;
2740 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2741 return tmp;
2745 /* Like gfc_conv_array_stride, but for the upper bound. */
2747 tree
2748 gfc_conv_array_ubound (tree descriptor, int dim)
2750 tree tmp;
2751 tree type;
2753 type = TREE_TYPE (descriptor);
2755 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2756 if (tmp != NULL_TREE)
2757 return tmp;
2759 /* This should only ever happen when passing an assumed shape array
2760 as an actual parameter. The value will never be used. */
2761 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2762 return gfc_index_zero_node;
2764 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2765 return tmp;
2769 /* Generate code to perform an array index bound check. */
2771 static tree
2772 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
2773 locus * where, bool check_upper)
2775 tree fault;
2776 tree tmp_lo, tmp_up;
2777 tree descriptor;
2778 char *msg;
2779 const char * name = NULL;
2781 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2782 return index;
2784 descriptor = ss->info->data.array.descriptor;
2786 index = gfc_evaluate_now (index, &se->pre);
2788 /* We find a name for the error message. */
2789 name = ss->info->expr->symtree->n.sym->name;
2790 gcc_assert (name != NULL);
2792 if (TREE_CODE (descriptor) == VAR_DECL)
2793 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
2795 /* If upper bound is present, include both bounds in the error message. */
2796 if (check_upper)
2798 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2799 tmp_up = gfc_conv_array_ubound (descriptor, n);
2801 if (name)
2802 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
2803 "outside of expected range (%%ld:%%ld)", n+1, name);
2804 else
2805 msg = xasprintf ("Index '%%ld' of dimension %d "
2806 "outside of expected range (%%ld:%%ld)", n+1);
2808 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2809 index, tmp_lo);
2810 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2811 fold_convert (long_integer_type_node, index),
2812 fold_convert (long_integer_type_node, tmp_lo),
2813 fold_convert (long_integer_type_node, tmp_up));
2814 fault = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2815 index, tmp_up);
2816 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2817 fold_convert (long_integer_type_node, index),
2818 fold_convert (long_integer_type_node, tmp_lo),
2819 fold_convert (long_integer_type_node, tmp_up));
2820 free (msg);
2822 else
2824 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2826 if (name)
2827 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
2828 "below lower bound of %%ld", n+1, name);
2829 else
2830 msg = xasprintf ("Index '%%ld' of dimension %d "
2831 "below lower bound of %%ld", n+1);
2833 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2834 index, tmp_lo);
2835 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2836 fold_convert (long_integer_type_node, index),
2837 fold_convert (long_integer_type_node, tmp_lo));
2838 free (msg);
2841 return index;
2845 /* Return the offset for an index. Performs bound checking for elemental
2846 dimensions. Single element references are processed separately.
2847 DIM is the array dimension, I is the loop dimension. */
2849 static tree
2850 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
2851 gfc_array_ref * ar, tree stride)
2853 gfc_array_info *info;
2854 tree index;
2855 tree desc;
2856 tree data;
2858 info = &ss->info->data.array;
2860 /* Get the index into the array for this dimension. */
2861 if (ar)
2863 gcc_assert (ar->type != AR_ELEMENT);
2864 switch (ar->dimen_type[dim])
2866 case DIMEN_THIS_IMAGE:
2867 gcc_unreachable ();
2868 break;
2869 case DIMEN_ELEMENT:
2870 /* Elemental dimension. */
2871 gcc_assert (info->subscript[dim]
2872 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
2873 /* We've already translated this value outside the loop. */
2874 index = info->subscript[dim]->info->data.scalar.value;
2876 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2877 ar->as->type != AS_ASSUMED_SIZE
2878 || dim < ar->dimen - 1);
2879 break;
2881 case DIMEN_VECTOR:
2882 gcc_assert (info && se->loop);
2883 gcc_assert (info->subscript[dim]
2884 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2885 desc = info->subscript[dim]->info->data.array.descriptor;
2887 /* Get a zero-based index into the vector. */
2888 index = fold_build2_loc (input_location, MINUS_EXPR,
2889 gfc_array_index_type,
2890 se->loop->loopvar[i], se->loop->from[i]);
2892 /* Multiply the index by the stride. */
2893 index = fold_build2_loc (input_location, MULT_EXPR,
2894 gfc_array_index_type,
2895 index, gfc_conv_array_stride (desc, 0));
2897 /* Read the vector to get an index into info->descriptor. */
2898 data = build_fold_indirect_ref_loc (input_location,
2899 gfc_conv_array_data (desc));
2900 index = gfc_build_array_ref (data, index, NULL);
2901 index = gfc_evaluate_now (index, &se->pre);
2902 index = fold_convert (gfc_array_index_type, index);
2904 /* Do any bounds checking on the final info->descriptor index. */
2905 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2906 ar->as->type != AS_ASSUMED_SIZE
2907 || dim < ar->dimen - 1);
2908 break;
2910 case DIMEN_RANGE:
2911 /* Scalarized dimension. */
2912 gcc_assert (info && se->loop);
2914 /* Multiply the loop variable by the stride and delta. */
2915 index = se->loop->loopvar[i];
2916 if (!integer_onep (info->stride[dim]))
2917 index = fold_build2_loc (input_location, MULT_EXPR,
2918 gfc_array_index_type, index,
2919 info->stride[dim]);
2920 if (!integer_zerop (info->delta[dim]))
2921 index = fold_build2_loc (input_location, PLUS_EXPR,
2922 gfc_array_index_type, index,
2923 info->delta[dim]);
2924 break;
2926 default:
2927 gcc_unreachable ();
2930 else
2932 /* Temporary array or derived type component. */
2933 gcc_assert (se->loop);
2934 index = se->loop->loopvar[se->loop->order[i]];
2936 /* Pointer functions can have stride[0] different from unity.
2937 Use the stride returned by the function call and stored in
2938 the descriptor for the temporary. */
2939 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
2940 && se->ss->info->expr
2941 && se->ss->info->expr->symtree
2942 && se->ss->info->expr->symtree->n.sym->result
2943 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
2944 stride = gfc_conv_descriptor_stride_get (info->descriptor,
2945 gfc_rank_cst[dim]);
2947 if (!integer_zerop (info->delta[dim]))
2948 index = fold_build2_loc (input_location, PLUS_EXPR,
2949 gfc_array_index_type, index, info->delta[dim]);
2952 /* Multiply by the stride. */
2953 if (!integer_onep (stride))
2954 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2955 index, stride);
2957 return index;
2961 /* Build a scalarized array reference using the vptr 'size'. */
2963 static bool
2964 build_class_array_ref (gfc_se *se, tree base, tree index)
2966 tree type;
2967 tree size;
2968 tree offset;
2969 tree decl;
2970 tree tmp;
2971 gfc_expr *expr = se->ss->info->expr;
2972 gfc_ref *ref;
2973 gfc_ref *class_ref;
2974 gfc_typespec *ts;
2976 if (expr == NULL || expr->ts.type != BT_CLASS)
2977 return false;
2979 if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS)
2980 ts = &expr->symtree->n.sym->ts;
2981 else
2982 ts = NULL;
2983 class_ref = NULL;
2985 for (ref = expr->ref; ref; ref = ref->next)
2987 if (ref->type == REF_COMPONENT
2988 && ref->u.c.component->ts.type == BT_CLASS
2989 && ref->next && ref->next->type == REF_COMPONENT
2990 && strcmp (ref->next->u.c.component->name, "_data") == 0
2991 && ref->next->next
2992 && ref->next->next->type == REF_ARRAY
2993 && ref->next->next->u.ar.type != AR_ELEMENT)
2995 ts = &ref->u.c.component->ts;
2996 class_ref = ref;
2997 break;
3001 if (ts == NULL)
3002 return false;
3004 if (class_ref == NULL && expr->symtree->n.sym->attr.function
3005 && expr->symtree->n.sym == expr->symtree->n.sym->result)
3007 gcc_assert (expr->symtree->n.sym->backend_decl == current_function_decl);
3008 decl = gfc_get_fake_result_decl (expr->symtree->n.sym, 0);
3010 else if (class_ref == NULL)
3011 decl = expr->symtree->n.sym->backend_decl;
3012 else
3014 /* Remove everything after the last class reference, convert the
3015 expression and then recover its tailend once more. */
3016 gfc_se tmpse;
3017 ref = class_ref->next;
3018 class_ref->next = NULL;
3019 gfc_init_se (&tmpse, NULL);
3020 gfc_conv_expr (&tmpse, expr);
3021 decl = tmpse.expr;
3022 class_ref->next = ref;
3025 size = gfc_vtable_size_get (decl);
3027 /* Build the address of the element. */
3028 type = TREE_TYPE (TREE_TYPE (base));
3029 size = fold_convert (TREE_TYPE (index), size);
3030 offset = fold_build2_loc (input_location, MULT_EXPR,
3031 gfc_array_index_type,
3032 index, size);
3033 tmp = gfc_build_addr_expr (pvoid_type_node, base);
3034 tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
3035 tmp = fold_convert (build_pointer_type (type), tmp);
3037 /* Return the element in the se expression. */
3038 se->expr = build_fold_indirect_ref_loc (input_location, tmp);
3039 return true;
3043 /* Build a scalarized reference to an array. */
3045 static void
3046 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
3048 gfc_array_info *info;
3049 tree decl = NULL_TREE;
3050 tree index;
3051 tree tmp;
3052 gfc_ss *ss;
3053 gfc_expr *expr;
3054 int n;
3056 ss = se->ss;
3057 expr = ss->info->expr;
3058 info = &ss->info->data.array;
3059 if (ar)
3060 n = se->loop->order[0];
3061 else
3062 n = 0;
3064 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
3065 /* Add the offset for this dimension to the stored offset for all other
3066 dimensions. */
3067 if (!integer_zerop (info->offset))
3068 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3069 index, info->offset);
3071 if (expr && is_subref_array (expr))
3072 decl = expr->symtree->n.sym->backend_decl;
3074 tmp = build_fold_indirect_ref_loc (input_location, info->data);
3076 /* Use the vptr 'size' field to access a class the element of a class
3077 array. */
3078 if (build_class_array_ref (se, tmp, index))
3079 return;
3081 se->expr = gfc_build_array_ref (tmp, index, decl);
3085 /* Translate access of temporary array. */
3087 void
3088 gfc_conv_tmp_array_ref (gfc_se * se)
3090 se->string_length = se->ss->info->string_length;
3091 gfc_conv_scalarized_array_ref (se, NULL);
3092 gfc_advance_se_ss_chain (se);
3095 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3097 static void
3098 add_to_offset (tree *cst_offset, tree *offset, tree t)
3100 if (TREE_CODE (t) == INTEGER_CST)
3101 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3102 else
3104 if (!integer_zerop (*offset))
3105 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3106 gfc_array_index_type, *offset, t);
3107 else
3108 *offset = t;
3113 static tree
3114 build_array_ref (tree desc, tree offset, tree decl)
3116 tree tmp;
3117 tree type;
3119 /* Class container types do not always have the GFC_CLASS_TYPE_P
3120 but the canonical type does. */
3121 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
3122 && TREE_CODE (desc) == COMPONENT_REF)
3124 type = TREE_TYPE (TREE_OPERAND (desc, 0));
3125 if (TYPE_CANONICAL (type)
3126 && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
3127 type = TYPE_CANONICAL (type);
3129 else
3130 type = NULL;
3132 /* Class array references need special treatment because the assigned
3133 type size needs to be used to point to the element. */
3134 if (type && GFC_CLASS_TYPE_P (type))
3136 type = gfc_get_element_type (TREE_TYPE (desc));
3137 tmp = TREE_OPERAND (desc, 0);
3138 tmp = gfc_get_class_array_ref (offset, tmp);
3139 tmp = fold_convert (build_pointer_type (type), tmp);
3140 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3141 return tmp;
3144 tmp = gfc_conv_array_data (desc);
3145 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3146 tmp = gfc_build_array_ref (tmp, offset, decl);
3147 return tmp;
3151 /* Build an array reference. se->expr already holds the array descriptor.
3152 This should be either a variable, indirect variable reference or component
3153 reference. For arrays which do not have a descriptor, se->expr will be
3154 the data pointer.
3155 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3157 void
3158 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_expr *expr,
3159 locus * where)
3161 int n;
3162 tree offset, cst_offset;
3163 tree tmp;
3164 tree stride;
3165 gfc_se indexse;
3166 gfc_se tmpse;
3167 gfc_symbol * sym = expr->symtree->n.sym;
3168 char *var_name = NULL;
3170 if (ar->dimen == 0)
3172 gcc_assert (ar->codimen);
3174 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3175 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
3176 else
3178 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
3179 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
3180 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
3182 /* Use the actual tree type and not the wrapped coarray. */
3183 if (!se->want_pointer)
3184 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
3185 se->expr);
3188 return;
3191 /* Handle scalarized references separately. */
3192 if (ar->type != AR_ELEMENT)
3194 gfc_conv_scalarized_array_ref (se, ar);
3195 gfc_advance_se_ss_chain (se);
3196 return;
3199 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3201 size_t len;
3202 gfc_ref *ref;
3204 len = strlen (sym->name) + 1;
3205 for (ref = expr->ref; ref; ref = ref->next)
3207 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3208 break;
3209 if (ref->type == REF_COMPONENT)
3210 len += 1 + strlen (ref->u.c.component->name);
3213 var_name = XALLOCAVEC (char, len);
3214 strcpy (var_name, sym->name);
3216 for (ref = expr->ref; ref; ref = ref->next)
3218 if (ref->type == REF_ARRAY && &ref->u.ar == ar)
3219 break;
3220 if (ref->type == REF_COMPONENT)
3222 strcat (var_name, "%%");
3223 strcat (var_name, ref->u.c.component->name);
3228 cst_offset = offset = gfc_index_zero_node;
3229 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
3231 /* Calculate the offsets from all the dimensions. Make sure to associate
3232 the final offset so that we form a chain of loop invariant summands. */
3233 for (n = ar->dimen - 1; n >= 0; n--)
3235 /* Calculate the index for this dimension. */
3236 gfc_init_se (&indexse, se);
3237 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
3238 gfc_add_block_to_block (&se->pre, &indexse.pre);
3240 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3242 /* Check array bounds. */
3243 tree cond;
3244 char *msg;
3246 /* Evaluate the indexse.expr only once. */
3247 indexse.expr = save_expr (indexse.expr);
3249 /* Lower bound. */
3250 tmp = gfc_conv_array_lbound (se->expr, n);
3251 if (sym->attr.temporary)
3253 gfc_init_se (&tmpse, se);
3254 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
3255 gfc_array_index_type);
3256 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3257 tmp = tmpse.expr;
3260 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
3261 indexse.expr, tmp);
3262 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3263 "below lower bound of %%ld", n+1, var_name);
3264 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3265 fold_convert (long_integer_type_node,
3266 indexse.expr),
3267 fold_convert (long_integer_type_node, tmp));
3268 free (msg);
3270 /* Upper bound, but not for the last dimension of assumed-size
3271 arrays. */
3272 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
3274 tmp = gfc_conv_array_ubound (se->expr, n);
3275 if (sym->attr.temporary)
3277 gfc_init_se (&tmpse, se);
3278 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
3279 gfc_array_index_type);
3280 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3281 tmp = tmpse.expr;
3284 cond = fold_build2_loc (input_location, GT_EXPR,
3285 boolean_type_node, indexse.expr, tmp);
3286 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
3287 "above upper bound of %%ld", n+1, var_name);
3288 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3289 fold_convert (long_integer_type_node,
3290 indexse.expr),
3291 fold_convert (long_integer_type_node, tmp));
3292 free (msg);
3296 /* Multiply the index by the stride. */
3297 stride = gfc_conv_array_stride (se->expr, n);
3298 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3299 indexse.expr, stride);
3301 /* And add it to the total. */
3302 add_to_offset (&cst_offset, &offset, tmp);
3305 if (!integer_zerop (cst_offset))
3306 offset = fold_build2_loc (input_location, PLUS_EXPR,
3307 gfc_array_index_type, offset, cst_offset);
3309 se->expr = build_array_ref (se->expr, offset, sym->backend_decl);
3313 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
3314 LOOP_DIM dimension (if any) to array's offset. */
3316 static void
3317 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
3318 gfc_array_ref *ar, int array_dim, int loop_dim)
3320 gfc_se se;
3321 gfc_array_info *info;
3322 tree stride, index;
3324 info = &ss->info->data.array;
3326 gfc_init_se (&se, NULL);
3327 se.loop = loop;
3328 se.expr = info->descriptor;
3329 stride = gfc_conv_array_stride (info->descriptor, array_dim);
3330 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
3331 gfc_add_block_to_block (pblock, &se.pre);
3333 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
3334 gfc_array_index_type,
3335 info->offset, index);
3336 info->offset = gfc_evaluate_now (info->offset, pblock);
3340 /* Generate the code to be executed immediately before entering a
3341 scalarization loop. */
3343 static void
3344 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
3345 stmtblock_t * pblock)
3347 tree stride;
3348 gfc_ss_info *ss_info;
3349 gfc_array_info *info;
3350 gfc_ss_type ss_type;
3351 gfc_ss *ss, *pss;
3352 gfc_loopinfo *ploop;
3353 gfc_array_ref *ar;
3354 int i;
3356 /* This code will be executed before entering the scalarization loop
3357 for this dimension. */
3358 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3360 ss_info = ss->info;
3362 if ((ss_info->useflags & flag) == 0)
3363 continue;
3365 ss_type = ss_info->type;
3366 if (ss_type != GFC_SS_SECTION
3367 && ss_type != GFC_SS_FUNCTION
3368 && ss_type != GFC_SS_CONSTRUCTOR
3369 && ss_type != GFC_SS_COMPONENT)
3370 continue;
3372 info = &ss_info->data.array;
3374 gcc_assert (dim < ss->dimen);
3375 gcc_assert (ss->dimen == loop->dimen);
3377 if (info->ref)
3378 ar = &info->ref->u.ar;
3379 else
3380 ar = NULL;
3382 if (dim == loop->dimen - 1 && loop->parent != NULL)
3384 /* If we are in the outermost dimension of this loop, the previous
3385 dimension shall be in the parent loop. */
3386 gcc_assert (ss->parent != NULL);
3388 pss = ss->parent;
3389 ploop = loop->parent;
3391 /* ss and ss->parent are about the same array. */
3392 gcc_assert (ss_info == pss->info);
3394 else
3396 ploop = loop;
3397 pss = ss;
3400 if (dim == loop->dimen - 1)
3401 i = 0;
3402 else
3403 i = dim + 1;
3405 /* For the time being, there is no loop reordering. */
3406 gcc_assert (i == ploop->order[i]);
3407 i = ploop->order[i];
3409 if (dim == loop->dimen - 1 && loop->parent == NULL)
3411 stride = gfc_conv_array_stride (info->descriptor,
3412 innermost_ss (ss)->dim[i]);
3414 /* Calculate the stride of the innermost loop. Hopefully this will
3415 allow the backend optimizers to do their stuff more effectively.
3417 info->stride0 = gfc_evaluate_now (stride, pblock);
3419 /* For the outermost loop calculate the offset due to any
3420 elemental dimensions. It will have been initialized with the
3421 base offset of the array. */
3422 if (info->ref)
3424 for (i = 0; i < ar->dimen; i++)
3426 if (ar->dimen_type[i] != DIMEN_ELEMENT)
3427 continue;
3429 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
3433 else
3434 /* Add the offset for the previous loop dimension. */
3435 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
3437 /* Remember this offset for the second loop. */
3438 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
3439 info->saved_offset = info->offset;
3444 /* Start a scalarized expression. Creates a scope and declares loop
3445 variables. */
3447 void
3448 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
3450 int dim;
3451 int n;
3452 int flags;
3454 gcc_assert (!loop->array_parameter);
3456 for (dim = loop->dimen - 1; dim >= 0; dim--)
3458 n = loop->order[dim];
3460 gfc_start_block (&loop->code[n]);
3462 /* Create the loop variable. */
3463 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
3465 if (dim < loop->temp_dim)
3466 flags = 3;
3467 else
3468 flags = 1;
3469 /* Calculate values that will be constant within this loop. */
3470 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3472 gfc_start_block (pbody);
3476 /* Generates the actual loop code for a scalarization loop. */
3478 void
3479 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3480 stmtblock_t * pbody)
3482 stmtblock_t block;
3483 tree cond;
3484 tree tmp;
3485 tree loopbody;
3486 tree exit_label;
3487 tree stmt;
3488 tree init;
3489 tree incr;
3491 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
3492 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3493 && n == loop->dimen - 1)
3495 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3496 init = make_tree_vec (1);
3497 cond = make_tree_vec (1);
3498 incr = make_tree_vec (1);
3500 /* Cycle statement is implemented with a goto. Exit statement must not
3501 be present for this loop. */
3502 exit_label = gfc_build_label_decl (NULL_TREE);
3503 TREE_USED (exit_label) = 1;
3505 /* Label for cycle statements (if needed). */
3506 tmp = build1_v (LABEL_EXPR, exit_label);
3507 gfc_add_expr_to_block (pbody, tmp);
3509 stmt = make_node (OMP_FOR);
3511 TREE_TYPE (stmt) = void_type_node;
3512 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3514 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3515 OMP_CLAUSE_SCHEDULE);
3516 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3517 = OMP_CLAUSE_SCHEDULE_STATIC;
3518 if (ompws_flags & OMPWS_NOWAIT)
3519 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3520 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3522 /* Initialize the loopvar. */
3523 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3524 loop->from[n]);
3525 OMP_FOR_INIT (stmt) = init;
3526 /* The exit condition. */
3527 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3528 boolean_type_node,
3529 loop->loopvar[n], loop->to[n]);
3530 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3531 OMP_FOR_COND (stmt) = cond;
3532 /* Increment the loopvar. */
3533 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3534 loop->loopvar[n], gfc_index_one_node);
3535 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3536 void_type_node, loop->loopvar[n], tmp);
3537 OMP_FOR_INCR (stmt) = incr;
3539 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3540 gfc_add_expr_to_block (&loop->code[n], stmt);
3542 else
3544 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3545 && (loop->temp_ss == NULL);
3547 loopbody = gfc_finish_block (pbody);
3549 if (reverse_loop)
3551 tmp = loop->from[n];
3552 loop->from[n] = loop->to[n];
3553 loop->to[n] = tmp;
3556 /* Initialize the loopvar. */
3557 if (loop->loopvar[n] != loop->from[n])
3558 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3560 exit_label = gfc_build_label_decl (NULL_TREE);
3562 /* Generate the loop body. */
3563 gfc_init_block (&block);
3565 /* The exit condition. */
3566 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3567 boolean_type_node, loop->loopvar[n], loop->to[n]);
3568 tmp = build1_v (GOTO_EXPR, exit_label);
3569 TREE_USED (exit_label) = 1;
3570 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3571 gfc_add_expr_to_block (&block, tmp);
3573 /* The main body. */
3574 gfc_add_expr_to_block (&block, loopbody);
3576 /* Increment the loopvar. */
3577 tmp = fold_build2_loc (input_location,
3578 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3579 gfc_array_index_type, loop->loopvar[n],
3580 gfc_index_one_node);
3582 gfc_add_modify (&block, loop->loopvar[n], tmp);
3584 /* Build the loop. */
3585 tmp = gfc_finish_block (&block);
3586 tmp = build1_v (LOOP_EXPR, tmp);
3587 gfc_add_expr_to_block (&loop->code[n], tmp);
3589 /* Add the exit label. */
3590 tmp = build1_v (LABEL_EXPR, exit_label);
3591 gfc_add_expr_to_block (&loop->code[n], tmp);
3597 /* Finishes and generates the loops for a scalarized expression. */
3599 void
3600 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3602 int dim;
3603 int n;
3604 gfc_ss *ss;
3605 stmtblock_t *pblock;
3606 tree tmp;
3608 pblock = body;
3609 /* Generate the loops. */
3610 for (dim = 0; dim < loop->dimen; dim++)
3612 n = loop->order[dim];
3613 gfc_trans_scalarized_loop_end (loop, n, pblock);
3614 loop->loopvar[n] = NULL_TREE;
3615 pblock = &loop->code[n];
3618 tmp = gfc_finish_block (pblock);
3619 gfc_add_expr_to_block (&loop->pre, tmp);
3621 /* Clear all the used flags. */
3622 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3623 if (ss->parent == NULL)
3624 ss->info->useflags = 0;
3628 /* Finish the main body of a scalarized expression, and start the secondary
3629 copying body. */
3631 void
3632 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
3634 int dim;
3635 int n;
3636 stmtblock_t *pblock;
3637 gfc_ss *ss;
3639 pblock = body;
3640 /* We finish as many loops as are used by the temporary. */
3641 for (dim = 0; dim < loop->temp_dim - 1; dim++)
3643 n = loop->order[dim];
3644 gfc_trans_scalarized_loop_end (loop, n, pblock);
3645 loop->loopvar[n] = NULL_TREE;
3646 pblock = &loop->code[n];
3649 /* We don't want to finish the outermost loop entirely. */
3650 n = loop->order[loop->temp_dim - 1];
3651 gfc_trans_scalarized_loop_end (loop, n, pblock);
3653 /* Restore the initial offsets. */
3654 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3656 gfc_ss_type ss_type;
3657 gfc_ss_info *ss_info;
3659 ss_info = ss->info;
3661 if ((ss_info->useflags & 2) == 0)
3662 continue;
3664 ss_type = ss_info->type;
3665 if (ss_type != GFC_SS_SECTION
3666 && ss_type != GFC_SS_FUNCTION
3667 && ss_type != GFC_SS_CONSTRUCTOR
3668 && ss_type != GFC_SS_COMPONENT)
3669 continue;
3671 ss_info->data.array.offset = ss_info->data.array.saved_offset;
3674 /* Restart all the inner loops we just finished. */
3675 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
3677 n = loop->order[dim];
3679 gfc_start_block (&loop->code[n]);
3681 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
3683 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
3686 /* Start a block for the secondary copying code. */
3687 gfc_start_block (body);
3691 /* Precalculate (either lower or upper) bound of an array section.
3692 BLOCK: Block in which the (pre)calculation code will go.
3693 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
3694 VALUES[DIM]: Specified bound (NULL <=> unspecified).
3695 DESC: Array descriptor from which the bound will be picked if unspecified
3696 (either lower or upper bound according to LBOUND). */
3698 static void
3699 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
3700 tree desc, int dim, bool lbound)
3702 gfc_se se;
3703 gfc_expr * input_val = values[dim];
3704 tree *output = &bounds[dim];
3707 if (input_val)
3709 /* Specified section bound. */
3710 gfc_init_se (&se, NULL);
3711 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
3712 gfc_add_block_to_block (block, &se.pre);
3713 *output = se.expr;
3715 else
3717 /* No specific bound specified so use the bound of the array. */
3718 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
3719 gfc_conv_array_ubound (desc, dim);
3721 *output = gfc_evaluate_now (*output, block);
3725 /* Calculate the lower bound of an array section. */
3727 static void
3728 gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
3730 gfc_expr *stride = NULL;
3731 tree desc;
3732 gfc_se se;
3733 gfc_array_info *info;
3734 gfc_array_ref *ar;
3736 gcc_assert (ss->info->type == GFC_SS_SECTION);
3738 info = &ss->info->data.array;
3739 ar = &info->ref->u.ar;
3741 if (ar->dimen_type[dim] == DIMEN_VECTOR)
3743 /* We use a zero-based index to access the vector. */
3744 info->start[dim] = gfc_index_zero_node;
3745 info->end[dim] = NULL;
3746 info->stride[dim] = gfc_index_one_node;
3747 return;
3750 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
3751 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
3752 desc = info->descriptor;
3753 stride = ar->stride[dim];
3755 /* Calculate the start of the range. For vector subscripts this will
3756 be the range of the vector. */
3757 evaluate_bound (block, info->start, ar->start, desc, dim, true);
3759 /* Similarly calculate the end. Although this is not used in the
3760 scalarizer, it is needed when checking bounds and where the end
3761 is an expression with side-effects. */
3762 evaluate_bound (block, info->end, ar->end, desc, dim, false);
3764 /* Calculate the stride. */
3765 if (stride == NULL)
3766 info->stride[dim] = gfc_index_one_node;
3767 else
3769 gfc_init_se (&se, NULL);
3770 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3771 gfc_add_block_to_block (block, &se.pre);
3772 info->stride[dim] = gfc_evaluate_now (se.expr, block);
3777 /* Calculates the range start and stride for a SS chain. Also gets the
3778 descriptor and data pointer. The range of vector subscripts is the size
3779 of the vector. Array bounds are also checked. */
3781 void
3782 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3784 int n;
3785 tree tmp;
3786 gfc_ss *ss;
3787 tree desc;
3789 gfc_loopinfo * const outer_loop = outermost_loop (loop);
3791 loop->dimen = 0;
3792 /* Determine the rank of the loop. */
3793 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3795 switch (ss->info->type)
3797 case GFC_SS_SECTION:
3798 case GFC_SS_CONSTRUCTOR:
3799 case GFC_SS_FUNCTION:
3800 case GFC_SS_COMPONENT:
3801 loop->dimen = ss->dimen;
3802 goto done;
3804 /* As usual, lbound and ubound are exceptions!. */
3805 case GFC_SS_INTRINSIC:
3806 switch (ss->info->expr->value.function.isym->id)
3808 case GFC_ISYM_LBOUND:
3809 case GFC_ISYM_UBOUND:
3810 case GFC_ISYM_LCOBOUND:
3811 case GFC_ISYM_UCOBOUND:
3812 case GFC_ISYM_THIS_IMAGE:
3813 loop->dimen = ss->dimen;
3814 goto done;
3816 default:
3817 break;
3820 default:
3821 break;
3825 /* We should have determined the rank of the expression by now. If
3826 not, that's bad news. */
3827 gcc_unreachable ();
3829 done:
3830 /* Loop over all the SS in the chain. */
3831 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3833 gfc_ss_info *ss_info;
3834 gfc_array_info *info;
3835 gfc_expr *expr;
3837 ss_info = ss->info;
3838 expr = ss_info->expr;
3839 info = &ss_info->data.array;
3841 if (expr && expr->shape && !info->shape)
3842 info->shape = expr->shape;
3844 switch (ss_info->type)
3846 case GFC_SS_SECTION:
3847 /* Get the descriptor for the array. If it is a cross loops array,
3848 we got the descriptor already in the outermost loop. */
3849 if (ss->parent == NULL)
3850 gfc_conv_ss_descriptor (&outer_loop->pre, ss,
3851 !loop->array_parameter);
3853 for (n = 0; n < ss->dimen; n++)
3854 gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
3855 break;
3857 case GFC_SS_INTRINSIC:
3858 switch (expr->value.function.isym->id)
3860 /* Fall through to supply start and stride. */
3861 case GFC_ISYM_LBOUND:
3862 case GFC_ISYM_UBOUND:
3864 gfc_expr *arg;
3866 /* This is the variant without DIM=... */
3867 gcc_assert (expr->value.function.actual->next->expr == NULL);
3869 arg = expr->value.function.actual->expr;
3870 if (arg->rank == -1)
3872 gfc_se se;
3873 tree rank, tmp;
3875 /* The rank (hence the return value's shape) is unknown,
3876 we have to retrieve it. */
3877 gfc_init_se (&se, NULL);
3878 se.descriptor_only = 1;
3879 gfc_conv_expr (&se, arg);
3880 /* This is a bare variable, so there is no preliminary
3881 or cleanup code. */
3882 gcc_assert (se.pre.head == NULL_TREE
3883 && se.post.head == NULL_TREE);
3884 rank = gfc_conv_descriptor_rank (se.expr);
3885 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3886 gfc_array_index_type,
3887 fold_convert (gfc_array_index_type,
3888 rank),
3889 gfc_index_one_node);
3890 info->end[0] = gfc_evaluate_now (tmp, &outer_loop->pre);
3891 info->start[0] = gfc_index_zero_node;
3892 info->stride[0] = gfc_index_one_node;
3893 continue;
3895 /* Otherwise fall through GFC_SS_FUNCTION. */
3897 case GFC_ISYM_LCOBOUND:
3898 case GFC_ISYM_UCOBOUND:
3899 case GFC_ISYM_THIS_IMAGE:
3900 break;
3902 default:
3903 continue;
3906 case GFC_SS_CONSTRUCTOR:
3907 case GFC_SS_FUNCTION:
3908 for (n = 0; n < ss->dimen; n++)
3910 int dim = ss->dim[n];
3912 info->start[dim] = gfc_index_zero_node;
3913 info->end[dim] = gfc_index_zero_node;
3914 info->stride[dim] = gfc_index_one_node;
3916 break;
3918 default:
3919 break;
3923 /* The rest is just runtime bound checking. */
3924 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3926 stmtblock_t block;
3927 tree lbound, ubound;
3928 tree end;
3929 tree size[GFC_MAX_DIMENSIONS];
3930 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
3931 gfc_array_info *info;
3932 char *msg;
3933 int dim;
3935 gfc_start_block (&block);
3937 for (n = 0; n < loop->dimen; n++)
3938 size[n] = NULL_TREE;
3940 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3942 stmtblock_t inner;
3943 gfc_ss_info *ss_info;
3944 gfc_expr *expr;
3945 locus *expr_loc;
3946 const char *expr_name;
3948 ss_info = ss->info;
3949 if (ss_info->type != GFC_SS_SECTION)
3950 continue;
3952 /* Catch allocatable lhs in f2003. */
3953 if (flag_realloc_lhs && ss->is_alloc_lhs)
3954 continue;
3956 expr = ss_info->expr;
3957 expr_loc = &expr->where;
3958 expr_name = expr->symtree->name;
3960 gfc_start_block (&inner);
3962 /* TODO: range checking for mapped dimensions. */
3963 info = &ss_info->data.array;
3965 /* This code only checks ranges. Elemental and vector
3966 dimensions are checked later. */
3967 for (n = 0; n < loop->dimen; n++)
3969 bool check_upper;
3971 dim = ss->dim[n];
3972 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
3973 continue;
3975 if (dim == info->ref->u.ar.dimen - 1
3976 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
3977 check_upper = false;
3978 else
3979 check_upper = true;
3981 /* Zero stride is not allowed. */
3982 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
3983 info->stride[dim], gfc_index_zero_node);
3984 msg = xasprintf ("Zero stride is not allowed, for dimension %d "
3985 "of array '%s'", dim + 1, expr_name);
3986 gfc_trans_runtime_check (true, false, tmp, &inner,
3987 expr_loc, msg);
3988 free (msg);
3990 desc = info->descriptor;
3992 /* This is the run-time equivalent of resolve.c's
3993 check_dimension(). The logical is more readable there
3994 than it is here, with all the trees. */
3995 lbound = gfc_conv_array_lbound (desc, dim);
3996 end = info->end[dim];
3997 if (check_upper)
3998 ubound = gfc_conv_array_ubound (desc, dim);
3999 else
4000 ubound = NULL;
4002 /* non_zerosized is true when the selected range is not
4003 empty. */
4004 stride_pos = fold_build2_loc (input_location, GT_EXPR,
4005 boolean_type_node, info->stride[dim],
4006 gfc_index_zero_node);
4007 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
4008 info->start[dim], end);
4009 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4010 boolean_type_node, stride_pos, tmp);
4012 stride_neg = fold_build2_loc (input_location, LT_EXPR,
4013 boolean_type_node,
4014 info->stride[dim], gfc_index_zero_node);
4015 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4016 info->start[dim], end);
4017 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4018 boolean_type_node,
4019 stride_neg, tmp);
4020 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4021 boolean_type_node,
4022 stride_pos, stride_neg);
4024 /* Check the start of the range against the lower and upper
4025 bounds of the array, if the range is not empty.
4026 If upper bound is present, include both bounds in the
4027 error message. */
4028 if (check_upper)
4030 tmp = fold_build2_loc (input_location, LT_EXPR,
4031 boolean_type_node,
4032 info->start[dim], lbound);
4033 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4034 boolean_type_node,
4035 non_zerosized, tmp);
4036 tmp2 = fold_build2_loc (input_location, GT_EXPR,
4037 boolean_type_node,
4038 info->start[dim], ubound);
4039 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4040 boolean_type_node,
4041 non_zerosized, tmp2);
4042 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4043 "outside of expected range (%%ld:%%ld)",
4044 dim + 1, expr_name);
4045 gfc_trans_runtime_check (true, false, tmp, &inner,
4046 expr_loc, msg,
4047 fold_convert (long_integer_type_node, info->start[dim]),
4048 fold_convert (long_integer_type_node, lbound),
4049 fold_convert (long_integer_type_node, ubound));
4050 gfc_trans_runtime_check (true, false, tmp2, &inner,
4051 expr_loc, msg,
4052 fold_convert (long_integer_type_node, info->start[dim]),
4053 fold_convert (long_integer_type_node, lbound),
4054 fold_convert (long_integer_type_node, ubound));
4055 free (msg);
4057 else
4059 tmp = fold_build2_loc (input_location, LT_EXPR,
4060 boolean_type_node,
4061 info->start[dim], lbound);
4062 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4063 boolean_type_node, non_zerosized, tmp);
4064 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4065 "below lower bound of %%ld",
4066 dim + 1, expr_name);
4067 gfc_trans_runtime_check (true, false, tmp, &inner,
4068 expr_loc, msg,
4069 fold_convert (long_integer_type_node, info->start[dim]),
4070 fold_convert (long_integer_type_node, lbound));
4071 free (msg);
4074 /* Compute the last element of the range, which is not
4075 necessarily "end" (think 0:5:3, which doesn't contain 5)
4076 and check it against both lower and upper bounds. */
4078 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4079 gfc_array_index_type, end,
4080 info->start[dim]);
4081 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
4082 gfc_array_index_type, tmp,
4083 info->stride[dim]);
4084 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4085 gfc_array_index_type, end, tmp);
4086 tmp2 = fold_build2_loc (input_location, LT_EXPR,
4087 boolean_type_node, tmp, lbound);
4088 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4089 boolean_type_node, non_zerosized, tmp2);
4090 if (check_upper)
4092 tmp3 = fold_build2_loc (input_location, GT_EXPR,
4093 boolean_type_node, tmp, ubound);
4094 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4095 boolean_type_node, non_zerosized, tmp3);
4096 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4097 "outside of expected range (%%ld:%%ld)",
4098 dim + 1, expr_name);
4099 gfc_trans_runtime_check (true, false, tmp2, &inner,
4100 expr_loc, msg,
4101 fold_convert (long_integer_type_node, tmp),
4102 fold_convert (long_integer_type_node, ubound),
4103 fold_convert (long_integer_type_node, lbound));
4104 gfc_trans_runtime_check (true, false, tmp3, &inner,
4105 expr_loc, msg,
4106 fold_convert (long_integer_type_node, tmp),
4107 fold_convert (long_integer_type_node, ubound),
4108 fold_convert (long_integer_type_node, lbound));
4109 free (msg);
4111 else
4113 msg = xasprintf ("Index '%%ld' of dimension %d of array '%s' "
4114 "below lower bound of %%ld",
4115 dim + 1, expr_name);
4116 gfc_trans_runtime_check (true, false, tmp2, &inner,
4117 expr_loc, msg,
4118 fold_convert (long_integer_type_node, tmp),
4119 fold_convert (long_integer_type_node, lbound));
4120 free (msg);
4123 /* Check the section sizes match. */
4124 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4125 gfc_array_index_type, end,
4126 info->start[dim]);
4127 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4128 gfc_array_index_type, tmp,
4129 info->stride[dim]);
4130 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4131 gfc_array_index_type,
4132 gfc_index_one_node, tmp);
4133 tmp = fold_build2_loc (input_location, MAX_EXPR,
4134 gfc_array_index_type, tmp,
4135 build_int_cst (gfc_array_index_type, 0));
4136 /* We remember the size of the first section, and check all the
4137 others against this. */
4138 if (size[n])
4140 tmp3 = fold_build2_loc (input_location, NE_EXPR,
4141 boolean_type_node, tmp, size[n]);
4142 msg = xasprintf ("Array bound mismatch for dimension %d "
4143 "of array '%s' (%%ld/%%ld)",
4144 dim + 1, expr_name);
4146 gfc_trans_runtime_check (true, false, tmp3, &inner,
4147 expr_loc, msg,
4148 fold_convert (long_integer_type_node, tmp),
4149 fold_convert (long_integer_type_node, size[n]));
4151 free (msg);
4153 else
4154 size[n] = gfc_evaluate_now (tmp, &inner);
4157 tmp = gfc_finish_block (&inner);
4159 /* For optional arguments, only check bounds if the argument is
4160 present. */
4161 if (expr->symtree->n.sym->attr.optional
4162 || expr->symtree->n.sym->attr.not_always_present)
4163 tmp = build3_v (COND_EXPR,
4164 gfc_conv_expr_present (expr->symtree->n.sym),
4165 tmp, build_empty_stmt (input_location));
4167 gfc_add_expr_to_block (&block, tmp);
4171 tmp = gfc_finish_block (&block);
4172 gfc_add_expr_to_block (&outer_loop->pre, tmp);
4175 for (loop = loop->nested; loop; loop = loop->next)
4176 gfc_conv_ss_startstride (loop);
4179 /* Return true if both symbols could refer to the same data object. Does
4180 not take account of aliasing due to equivalence statements. */
4182 static int
4183 symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
4184 bool lsym_target, bool rsym_pointer, bool rsym_target)
4186 /* Aliasing isn't possible if the symbols have different base types. */
4187 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
4188 return 0;
4190 /* Pointers can point to other pointers and target objects. */
4192 if ((lsym_pointer && (rsym_pointer || rsym_target))
4193 || (rsym_pointer && (lsym_pointer || lsym_target)))
4194 return 1;
4196 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
4197 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
4198 checked above. */
4199 if (lsym_target && rsym_target
4200 && ((lsym->attr.dummy && !lsym->attr.contiguous
4201 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
4202 || (rsym->attr.dummy && !rsym->attr.contiguous
4203 && (!rsym->attr.dimension
4204 || rsym->as->type == AS_ASSUMED_SHAPE))))
4205 return 1;
4207 return 0;
4211 /* Return true if the two SS could be aliased, i.e. both point to the same data
4212 object. */
4213 /* TODO: resolve aliases based on frontend expressions. */
4215 static int
4216 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
4218 gfc_ref *lref;
4219 gfc_ref *rref;
4220 gfc_expr *lexpr, *rexpr;
4221 gfc_symbol *lsym;
4222 gfc_symbol *rsym;
4223 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
4225 lexpr = lss->info->expr;
4226 rexpr = rss->info->expr;
4228 lsym = lexpr->symtree->n.sym;
4229 rsym = rexpr->symtree->n.sym;
4231 lsym_pointer = lsym->attr.pointer;
4232 lsym_target = lsym->attr.target;
4233 rsym_pointer = rsym->attr.pointer;
4234 rsym_target = rsym->attr.target;
4236 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
4237 rsym_pointer, rsym_target))
4238 return 1;
4240 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
4241 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
4242 return 0;
4244 /* For derived types we must check all the component types. We can ignore
4245 array references as these will have the same base type as the previous
4246 component ref. */
4247 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
4249 if (lref->type != REF_COMPONENT)
4250 continue;
4252 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
4253 lsym_target = lsym_target || lref->u.c.sym->attr.target;
4255 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
4256 rsym_pointer, rsym_target))
4257 return 1;
4259 if ((lsym_pointer && (rsym_pointer || rsym_target))
4260 || (rsym_pointer && (lsym_pointer || lsym_target)))
4262 if (gfc_compare_types (&lref->u.c.component->ts,
4263 &rsym->ts))
4264 return 1;
4267 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
4268 rref = rref->next)
4270 if (rref->type != REF_COMPONENT)
4271 continue;
4273 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4274 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4276 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
4277 lsym_pointer, lsym_target,
4278 rsym_pointer, rsym_target))
4279 return 1;
4281 if ((lsym_pointer && (rsym_pointer || rsym_target))
4282 || (rsym_pointer && (lsym_pointer || lsym_target)))
4284 if (gfc_compare_types (&lref->u.c.component->ts,
4285 &rref->u.c.sym->ts))
4286 return 1;
4287 if (gfc_compare_types (&lref->u.c.sym->ts,
4288 &rref->u.c.component->ts))
4289 return 1;
4290 if (gfc_compare_types (&lref->u.c.component->ts,
4291 &rref->u.c.component->ts))
4292 return 1;
4297 lsym_pointer = lsym->attr.pointer;
4298 lsym_target = lsym->attr.target;
4299 lsym_pointer = lsym->attr.pointer;
4300 lsym_target = lsym->attr.target;
4302 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
4304 if (rref->type != REF_COMPONENT)
4305 break;
4307 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4308 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4310 if (symbols_could_alias (rref->u.c.sym, lsym,
4311 lsym_pointer, lsym_target,
4312 rsym_pointer, rsym_target))
4313 return 1;
4315 if ((lsym_pointer && (rsym_pointer || rsym_target))
4316 || (rsym_pointer && (lsym_pointer || lsym_target)))
4318 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
4319 return 1;
4323 return 0;
4327 /* Resolve array data dependencies. Creates a temporary if required. */
4328 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
4329 dependency.c. */
4331 void
4332 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
4333 gfc_ss * rss)
4335 gfc_ss *ss;
4336 gfc_ref *lref;
4337 gfc_ref *rref;
4338 gfc_expr *dest_expr;
4339 gfc_expr *ss_expr;
4340 int nDepend = 0;
4341 int i, j;
4343 loop->temp_ss = NULL;
4344 dest_expr = dest->info->expr;
4346 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
4348 ss_expr = ss->info->expr;
4350 if (ss->info->type != GFC_SS_SECTION)
4352 if (flag_realloc_lhs
4353 && dest_expr != ss_expr
4354 && gfc_is_reallocatable_lhs (dest_expr)
4355 && ss_expr->rank)
4356 nDepend = gfc_check_dependency (dest_expr, ss_expr, true);
4358 /* Check for cases like c(:)(1:2) = c(2)(2:3) */
4359 if (!nDepend && dest_expr->rank > 0
4360 && dest_expr->ts.type == BT_CHARACTER
4361 && ss_expr->expr_type == EXPR_VARIABLE)
4363 nDepend = gfc_check_dependency (dest_expr, ss_expr, false);
4365 continue;
4368 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
4370 if (gfc_could_be_alias (dest, ss)
4371 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
4373 nDepend = 1;
4374 break;
4377 else
4379 lref = dest_expr->ref;
4380 rref = ss_expr->ref;
4382 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
4384 if (nDepend == 1)
4385 break;
4387 for (i = 0; i < dest->dimen; i++)
4388 for (j = 0; j < ss->dimen; j++)
4389 if (i != j
4390 && dest->dim[i] == ss->dim[j])
4392 /* If we don't access array elements in the same order,
4393 there is a dependency. */
4394 nDepend = 1;
4395 goto temporary;
4397 #if 0
4398 /* TODO : loop shifting. */
4399 if (nDepend == 1)
4401 /* Mark the dimensions for LOOP SHIFTING */
4402 for (n = 0; n < loop->dimen; n++)
4404 int dim = dest->data.info.dim[n];
4406 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
4407 depends[n] = 2;
4408 else if (! gfc_is_same_range (&lref->u.ar,
4409 &rref->u.ar, dim, 0))
4410 depends[n] = 1;
4413 /* Put all the dimensions with dependencies in the
4414 innermost loops. */
4415 dim = 0;
4416 for (n = 0; n < loop->dimen; n++)
4418 gcc_assert (loop->order[n] == n);
4419 if (depends[n])
4420 loop->order[dim++] = n;
4422 for (n = 0; n < loop->dimen; n++)
4424 if (! depends[n])
4425 loop->order[dim++] = n;
4428 gcc_assert (dim == loop->dimen);
4429 break;
4431 #endif
4435 temporary:
4437 if (nDepend == 1)
4439 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
4440 if (GFC_ARRAY_TYPE_P (base_type)
4441 || GFC_DESCRIPTOR_TYPE_P (base_type))
4442 base_type = gfc_get_element_type (base_type);
4443 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
4444 loop->dimen);
4445 gfc_add_ss_to_loop (loop, loop->temp_ss);
4447 else
4448 loop->temp_ss = NULL;
4452 /* Browse through each array's information from the scalarizer and set the loop
4453 bounds according to the "best" one (per dimension), i.e. the one which
4454 provides the most information (constant bounds, shape, etc.). */
4456 static void
4457 set_loop_bounds (gfc_loopinfo *loop)
4459 int n, dim, spec_dim;
4460 gfc_array_info *info;
4461 gfc_array_info *specinfo;
4462 gfc_ss *ss;
4463 tree tmp;
4464 gfc_ss **loopspec;
4465 bool dynamic[GFC_MAX_DIMENSIONS];
4466 mpz_t *cshape;
4467 mpz_t i;
4468 bool nonoptional_arr;
4470 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4472 loopspec = loop->specloop;
4474 mpz_init (i);
4475 for (n = 0; n < loop->dimen; n++)
4477 loopspec[n] = NULL;
4478 dynamic[n] = false;
4480 /* If there are both optional and nonoptional array arguments, scalarize
4481 over the nonoptional; otherwise, it does not matter as then all
4482 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
4484 nonoptional_arr = false;
4486 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4487 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
4488 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
4490 nonoptional_arr = true;
4491 break;
4494 /* We use one SS term, and use that to determine the bounds of the
4495 loop for this dimension. We try to pick the simplest term. */
4496 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4498 gfc_ss_type ss_type;
4500 ss_type = ss->info->type;
4501 if (ss_type == GFC_SS_SCALAR
4502 || ss_type == GFC_SS_TEMP
4503 || ss_type == GFC_SS_REFERENCE
4504 || (ss->info->can_be_null_ref && nonoptional_arr))
4505 continue;
4507 info = &ss->info->data.array;
4508 dim = ss->dim[n];
4510 if (loopspec[n] != NULL)
4512 specinfo = &loopspec[n]->info->data.array;
4513 spec_dim = loopspec[n]->dim[n];
4515 else
4517 /* Silence uninitialized warnings. */
4518 specinfo = NULL;
4519 spec_dim = 0;
4522 if (info->shape)
4524 gcc_assert (info->shape[dim]);
4525 /* The frontend has worked out the size for us. */
4526 if (!loopspec[n]
4527 || !specinfo->shape
4528 || !integer_zerop (specinfo->start[spec_dim]))
4529 /* Prefer zero-based descriptors if possible. */
4530 loopspec[n] = ss;
4531 continue;
4534 if (ss_type == GFC_SS_CONSTRUCTOR)
4536 gfc_constructor_base base;
4537 /* An unknown size constructor will always be rank one.
4538 Higher rank constructors will either have known shape,
4539 or still be wrapped in a call to reshape. */
4540 gcc_assert (loop->dimen == 1);
4542 /* Always prefer to use the constructor bounds if the size
4543 can be determined at compile time. Prefer not to otherwise,
4544 since the general case involves realloc, and it's better to
4545 avoid that overhead if possible. */
4546 base = ss->info->expr->value.constructor;
4547 dynamic[n] = gfc_get_array_constructor_size (&i, base);
4548 if (!dynamic[n] || !loopspec[n])
4549 loopspec[n] = ss;
4550 continue;
4553 /* Avoid using an allocatable lhs in an assignment, since
4554 there might be a reallocation coming. */
4555 if (loopspec[n] && ss->is_alloc_lhs)
4556 continue;
4558 if (!loopspec[n])
4559 loopspec[n] = ss;
4560 /* Criteria for choosing a loop specifier (most important first):
4561 doesn't need realloc
4562 stride of one
4563 known stride
4564 known lower bound
4565 known upper bound
4567 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
4568 loopspec[n] = ss;
4569 else if (integer_onep (info->stride[dim])
4570 && !integer_onep (specinfo->stride[spec_dim]))
4571 loopspec[n] = ss;
4572 else if (INTEGER_CST_P (info->stride[dim])
4573 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
4574 loopspec[n] = ss;
4575 else if (INTEGER_CST_P (info->start[dim])
4576 && !INTEGER_CST_P (specinfo->start[spec_dim])
4577 && integer_onep (info->stride[dim])
4578 == integer_onep (specinfo->stride[spec_dim])
4579 && INTEGER_CST_P (info->stride[dim])
4580 == INTEGER_CST_P (specinfo->stride[spec_dim]))
4581 loopspec[n] = ss;
4582 /* We don't work out the upper bound.
4583 else if (INTEGER_CST_P (info->finish[n])
4584 && ! INTEGER_CST_P (specinfo->finish[n]))
4585 loopspec[n] = ss; */
4588 /* We should have found the scalarization loop specifier. If not,
4589 that's bad news. */
4590 gcc_assert (loopspec[n]);
4592 info = &loopspec[n]->info->data.array;
4593 dim = loopspec[n]->dim[n];
4595 /* Set the extents of this range. */
4596 cshape = info->shape;
4597 if (cshape && INTEGER_CST_P (info->start[dim])
4598 && INTEGER_CST_P (info->stride[dim]))
4600 loop->from[n] = info->start[dim];
4601 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
4602 mpz_sub_ui (i, i, 1);
4603 /* To = from + (size - 1) * stride. */
4604 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
4605 if (!integer_onep (info->stride[dim]))
4606 tmp = fold_build2_loc (input_location, MULT_EXPR,
4607 gfc_array_index_type, tmp,
4608 info->stride[dim]);
4609 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
4610 gfc_array_index_type,
4611 loop->from[n], tmp);
4613 else
4615 loop->from[n] = info->start[dim];
4616 switch (loopspec[n]->info->type)
4618 case GFC_SS_CONSTRUCTOR:
4619 /* The upper bound is calculated when we expand the
4620 constructor. */
4621 gcc_assert (loop->to[n] == NULL_TREE);
4622 break;
4624 case GFC_SS_SECTION:
4625 /* Use the end expression if it exists and is not constant,
4626 so that it is only evaluated once. */
4627 loop->to[n] = info->end[dim];
4628 break;
4630 case GFC_SS_FUNCTION:
4631 /* The loop bound will be set when we generate the call. */
4632 gcc_assert (loop->to[n] == NULL_TREE);
4633 break;
4635 case GFC_SS_INTRINSIC:
4637 gfc_expr *expr = loopspec[n]->info->expr;
4639 /* The {l,u}bound of an assumed rank. */
4640 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
4641 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
4642 && expr->value.function.actual->next->expr == NULL
4643 && expr->value.function.actual->expr->rank == -1);
4645 loop->to[n] = info->end[dim];
4646 break;
4649 default:
4650 gcc_unreachable ();
4654 /* Transform everything so we have a simple incrementing variable. */
4655 if (integer_onep (info->stride[dim]))
4656 info->delta[dim] = gfc_index_zero_node;
4657 else
4659 /* Set the delta for this section. */
4660 info->delta[dim] = gfc_evaluate_now (loop->from[n], &outer_loop->pre);
4661 /* Number of iterations is (end - start + step) / step.
4662 with start = 0, this simplifies to
4663 last = end / step;
4664 for (i = 0; i<=last; i++){...}; */
4665 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4666 gfc_array_index_type, loop->to[n],
4667 loop->from[n]);
4668 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4669 gfc_array_index_type, tmp, info->stride[dim]);
4670 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
4671 tmp, build_int_cst (gfc_array_index_type, -1));
4672 loop->to[n] = gfc_evaluate_now (tmp, &outer_loop->pre);
4673 /* Make the loop variable start at 0. */
4674 loop->from[n] = gfc_index_zero_node;
4677 mpz_clear (i);
4679 for (loop = loop->nested; loop; loop = loop->next)
4680 set_loop_bounds (loop);
4684 /* Initialize the scalarization loop. Creates the loop variables. Determines
4685 the range of the loop variables. Creates a temporary if required.
4686 Also generates code for scalar expressions which have been
4687 moved outside the loop. */
4689 void
4690 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
4692 gfc_ss *tmp_ss;
4693 tree tmp;
4695 set_loop_bounds (loop);
4697 /* Add all the scalar code that can be taken out of the loops.
4698 This may include calculating the loop bounds, so do it before
4699 allocating the temporary. */
4700 gfc_add_loop_ss_code (loop, loop->ss, false, where);
4702 tmp_ss = loop->temp_ss;
4703 /* If we want a temporary then create it. */
4704 if (tmp_ss != NULL)
4706 gfc_ss_info *tmp_ss_info;
4708 tmp_ss_info = tmp_ss->info;
4709 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
4710 gcc_assert (loop->parent == NULL);
4712 /* Make absolutely sure that this is a complete type. */
4713 if (tmp_ss_info->string_length)
4714 tmp_ss_info->data.temp.type
4715 = gfc_get_character_type_len_for_eltype
4716 (TREE_TYPE (tmp_ss_info->data.temp.type),
4717 tmp_ss_info->string_length);
4719 tmp = tmp_ss_info->data.temp.type;
4720 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
4721 tmp_ss_info->type = GFC_SS_SECTION;
4723 gcc_assert (tmp_ss->dimen != 0);
4725 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
4726 NULL_TREE, false, true, false, where);
4729 /* For array parameters we don't have loop variables, so don't calculate the
4730 translations. */
4731 if (!loop->array_parameter)
4732 gfc_set_delta (loop);
4736 /* Calculates how to transform from loop variables to array indices for each
4737 array: once loop bounds are chosen, sets the difference (DELTA field) between
4738 loop bounds and array reference bounds, for each array info. */
4740 void
4741 gfc_set_delta (gfc_loopinfo *loop)
4743 gfc_ss *ss, **loopspec;
4744 gfc_array_info *info;
4745 tree tmp;
4746 int n, dim;
4748 gfc_loopinfo * const outer_loop = outermost_loop (loop);
4750 loopspec = loop->specloop;
4752 /* Calculate the translation from loop variables to array indices. */
4753 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4755 gfc_ss_type ss_type;
4757 ss_type = ss->info->type;
4758 if (ss_type != GFC_SS_SECTION
4759 && ss_type != GFC_SS_COMPONENT
4760 && ss_type != GFC_SS_CONSTRUCTOR)
4761 continue;
4763 info = &ss->info->data.array;
4765 for (n = 0; n < ss->dimen; n++)
4767 /* If we are specifying the range the delta is already set. */
4768 if (loopspec[n] != ss)
4770 dim = ss->dim[n];
4772 /* Calculate the offset relative to the loop variable.
4773 First multiply by the stride. */
4774 tmp = loop->from[n];
4775 if (!integer_onep (info->stride[dim]))
4776 tmp = fold_build2_loc (input_location, MULT_EXPR,
4777 gfc_array_index_type,
4778 tmp, info->stride[dim]);
4780 /* Then subtract this from our starting value. */
4781 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4782 gfc_array_index_type,
4783 info->start[dim], tmp);
4785 info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
4790 for (loop = loop->nested; loop; loop = loop->next)
4791 gfc_set_delta (loop);
4795 /* Calculate the size of a given array dimension from the bounds. This
4796 is simply (ubound - lbound + 1) if this expression is positive
4797 or 0 if it is negative (pick either one if it is zero). Optionally
4798 (if or_expr is present) OR the (expression != 0) condition to it. */
4800 tree
4801 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
4803 tree res;
4804 tree cond;
4806 /* Calculate (ubound - lbound + 1). */
4807 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4808 ubound, lbound);
4809 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
4810 gfc_index_one_node);
4812 /* Check whether the size for this dimension is negative. */
4813 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, res,
4814 gfc_index_zero_node);
4815 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
4816 gfc_index_zero_node, res);
4818 /* Build OR expression. */
4819 if (or_expr)
4820 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4821 boolean_type_node, *or_expr, cond);
4823 return res;
4827 /* For an array descriptor, get the total number of elements. This is just
4828 the product of the extents along from_dim to to_dim. */
4830 static tree
4831 gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
4833 tree res;
4834 int dim;
4836 res = gfc_index_one_node;
4838 for (dim = from_dim; dim < to_dim; ++dim)
4840 tree lbound;
4841 tree ubound;
4842 tree extent;
4844 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
4845 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
4847 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
4848 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4849 res, extent);
4852 return res;
4856 /* Full size of an array. */
4858 tree
4859 gfc_conv_descriptor_size (tree desc, int rank)
4861 return gfc_conv_descriptor_size_1 (desc, 0, rank);
4865 /* Size of a coarray for all dimensions but the last. */
4867 tree
4868 gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
4870 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
4874 /* Fills in an array descriptor, and returns the size of the array.
4875 The size will be a simple_val, ie a variable or a constant. Also
4876 calculates the offset of the base. The pointer argument overflow,
4877 which should be of integer type, will increase in value if overflow
4878 occurs during the size calculation. Returns the size of the array.
4880 stride = 1;
4881 offset = 0;
4882 for (n = 0; n < rank; n++)
4884 a.lbound[n] = specified_lower_bound;
4885 offset = offset + a.lbond[n] * stride;
4886 size = 1 - lbound;
4887 a.ubound[n] = specified_upper_bound;
4888 a.stride[n] = stride;
4889 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
4890 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
4891 stride = stride * size;
4893 for (n = rank; n < rank+corank; n++)
4894 (Set lcobound/ucobound as above.)
4895 element_size = sizeof (array element);
4896 if (!rank)
4897 return element_size
4898 stride = (size_t) stride;
4899 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
4900 stride = stride * element_size;
4901 return (stride);
4902 } */
4903 /*GCC ARRAYS*/
4905 static tree
4906 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
4907 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
4908 stmtblock_t * descriptor_block, tree * overflow,
4909 tree expr3_elem_size, tree *nelems, gfc_expr *expr3,
4910 gfc_typespec *ts)
4912 tree type;
4913 tree tmp;
4914 tree size;
4915 tree offset;
4916 tree stride;
4917 tree element_size;
4918 tree or_expr;
4919 tree thencase;
4920 tree elsecase;
4921 tree cond;
4922 tree var;
4923 stmtblock_t thenblock;
4924 stmtblock_t elseblock;
4925 gfc_expr *ubound;
4926 gfc_se se;
4927 int n;
4929 type = TREE_TYPE (descriptor);
4931 stride = gfc_index_one_node;
4932 offset = gfc_index_zero_node;
4934 /* Set the dtype. */
4935 tmp = gfc_conv_descriptor_dtype (descriptor);
4936 gfc_add_modify (descriptor_block, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
4938 or_expr = boolean_false_node;
4940 for (n = 0; n < rank; n++)
4942 tree conv_lbound;
4943 tree conv_ubound;
4945 /* We have 3 possibilities for determining the size of the array:
4946 lower == NULL => lbound = 1, ubound = upper[n]
4947 upper[n] = NULL => lbound = 1, ubound = lower[n]
4948 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
4949 ubound = upper[n];
4951 /* Set lower bound. */
4952 gfc_init_se (&se, NULL);
4953 if (lower == NULL)
4954 se.expr = gfc_index_one_node;
4955 else
4957 gcc_assert (lower[n]);
4958 if (ubound)
4960 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
4961 gfc_add_block_to_block (pblock, &se.pre);
4963 else
4965 se.expr = gfc_index_one_node;
4966 ubound = lower[n];
4969 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
4970 gfc_rank_cst[n], se.expr);
4971 conv_lbound = se.expr;
4973 /* Work out the offset for this component. */
4974 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4975 se.expr, stride);
4976 offset = fold_build2_loc (input_location, MINUS_EXPR,
4977 gfc_array_index_type, offset, tmp);
4979 /* Set upper bound. */
4980 gfc_init_se (&se, NULL);
4981 gcc_assert (ubound);
4982 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
4983 gfc_add_block_to_block (pblock, &se.pre);
4985 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
4986 gfc_rank_cst[n], se.expr);
4987 conv_ubound = se.expr;
4989 /* Store the stride. */
4990 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
4991 gfc_rank_cst[n], stride);
4993 /* Calculate size and check whether extent is negative. */
4994 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
4995 size = gfc_evaluate_now (size, pblock);
4997 /* Check whether multiplying the stride by the number of
4998 elements in this dimension would overflow. We must also check
4999 whether the current dimension has zero size in order to avoid
5000 division by zero.
5002 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5003 gfc_array_index_type,
5004 fold_convert (gfc_array_index_type,
5005 TYPE_MAX_VALUE (gfc_array_index_type)),
5006 size);
5007 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5008 boolean_type_node, tmp, stride),
5009 PRED_FORTRAN_OVERFLOW);
5010 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5011 integer_one_node, integer_zero_node);
5012 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5013 boolean_type_node, size,
5014 gfc_index_zero_node),
5015 PRED_FORTRAN_SIZE_ZERO);
5016 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5017 integer_zero_node, tmp);
5018 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5019 *overflow, tmp);
5020 *overflow = gfc_evaluate_now (tmp, pblock);
5022 /* Multiply the stride by the number of elements in this dimension. */
5023 stride = fold_build2_loc (input_location, MULT_EXPR,
5024 gfc_array_index_type, stride, size);
5025 stride = gfc_evaluate_now (stride, pblock);
5028 for (n = rank; n < rank + corank; n++)
5030 ubound = upper[n];
5032 /* Set lower bound. */
5033 gfc_init_se (&se, NULL);
5034 if (lower == NULL || lower[n] == NULL)
5036 gcc_assert (n == rank + corank - 1);
5037 se.expr = gfc_index_one_node;
5039 else
5041 if (ubound || n == rank + corank - 1)
5043 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
5044 gfc_add_block_to_block (pblock, &se.pre);
5046 else
5048 se.expr = gfc_index_one_node;
5049 ubound = lower[n];
5052 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
5053 gfc_rank_cst[n], se.expr);
5055 if (n < rank + corank - 1)
5057 gfc_init_se (&se, NULL);
5058 gcc_assert (ubound);
5059 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
5060 gfc_add_block_to_block (pblock, &se.pre);
5061 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
5062 gfc_rank_cst[n], se.expr);
5066 /* The stride is the number of elements in the array, so multiply by the
5067 size of an element to get the total size. Obviously, if there is a
5068 SOURCE expression (expr3) we must use its element size. */
5069 if (expr3_elem_size != NULL_TREE)
5070 tmp = expr3_elem_size;
5071 else if (expr3 != NULL)
5073 if (expr3->ts.type == BT_CLASS)
5075 gfc_se se_sz;
5076 gfc_expr *sz = gfc_copy_expr (expr3);
5077 gfc_add_vptr_component (sz);
5078 gfc_add_size_component (sz);
5079 gfc_init_se (&se_sz, NULL);
5080 gfc_conv_expr (&se_sz, sz);
5081 gfc_free_expr (sz);
5082 tmp = se_sz.expr;
5084 else
5086 tmp = gfc_typenode_for_spec (&expr3->ts);
5087 tmp = TYPE_SIZE_UNIT (tmp);
5090 else if (ts->type != BT_UNKNOWN && ts->type != BT_CHARACTER)
5091 /* FIXME: Properly handle characters. See PR 57456. */
5092 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (ts));
5093 else
5094 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5096 /* Convert to size_t. */
5097 element_size = fold_convert (size_type_node, tmp);
5099 if (rank == 0)
5100 return element_size;
5102 *nelems = gfc_evaluate_now (stride, pblock);
5103 stride = fold_convert (size_type_node, stride);
5105 /* First check for overflow. Since an array of type character can
5106 have zero element_size, we must check for that before
5107 dividing. */
5108 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5109 size_type_node,
5110 TYPE_MAX_VALUE (size_type_node), element_size);
5111 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5112 boolean_type_node, tmp, stride),
5113 PRED_FORTRAN_OVERFLOW);
5114 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5115 integer_one_node, integer_zero_node);
5116 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5117 boolean_type_node, element_size,
5118 build_int_cst (size_type_node, 0)),
5119 PRED_FORTRAN_SIZE_ZERO);
5120 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5121 integer_zero_node, tmp);
5122 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5123 *overflow, tmp);
5124 *overflow = gfc_evaluate_now (tmp, pblock);
5126 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
5127 stride, element_size);
5129 if (poffset != NULL)
5131 offset = gfc_evaluate_now (offset, pblock);
5132 *poffset = offset;
5135 if (integer_zerop (or_expr))
5136 return size;
5137 if (integer_onep (or_expr))
5138 return build_int_cst (size_type_node, 0);
5140 var = gfc_create_var (TREE_TYPE (size), "size");
5141 gfc_start_block (&thenblock);
5142 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
5143 thencase = gfc_finish_block (&thenblock);
5145 gfc_start_block (&elseblock);
5146 gfc_add_modify (&elseblock, var, size);
5147 elsecase = gfc_finish_block (&elseblock);
5149 tmp = gfc_evaluate_now (or_expr, pblock);
5150 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
5151 gfc_add_expr_to_block (pblock, tmp);
5153 return var;
5157 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
5158 the work for an ALLOCATE statement. */
5159 /*GCC ARRAYS*/
5161 bool
5162 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
5163 tree errlen, tree label_finish, tree expr3_elem_size,
5164 tree *nelems, gfc_expr *expr3, gfc_typespec *ts)
5166 tree tmp;
5167 tree pointer;
5168 tree offset = NULL_TREE;
5169 tree token = NULL_TREE;
5170 tree size;
5171 tree msg;
5172 tree error = NULL_TREE;
5173 tree overflow; /* Boolean storing whether size calculation overflows. */
5174 tree var_overflow = NULL_TREE;
5175 tree cond;
5176 tree set_descriptor;
5177 stmtblock_t set_descriptor_block;
5178 stmtblock_t elseblock;
5179 gfc_expr **lower;
5180 gfc_expr **upper;
5181 gfc_ref *ref, *prev_ref = NULL;
5182 bool allocatable, coarray, dimension;
5184 ref = expr->ref;
5186 /* Find the last reference in the chain. */
5187 while (ref && ref->next != NULL)
5189 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
5190 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
5191 prev_ref = ref;
5192 ref = ref->next;
5195 if (ref == NULL || ref->type != REF_ARRAY)
5196 return false;
5198 if (!prev_ref)
5200 allocatable = expr->symtree->n.sym->attr.allocatable;
5201 coarray = expr->symtree->n.sym->attr.codimension;
5202 dimension = expr->symtree->n.sym->attr.dimension;
5204 else
5206 allocatable = prev_ref->u.c.component->attr.allocatable;
5207 coarray = prev_ref->u.c.component->attr.codimension;
5208 dimension = prev_ref->u.c.component->attr.dimension;
5211 if (!dimension)
5212 gcc_assert (coarray);
5214 /* Figure out the size of the array. */
5215 switch (ref->u.ar.type)
5217 case AR_ELEMENT:
5218 if (!coarray)
5220 lower = NULL;
5221 upper = ref->u.ar.start;
5222 break;
5224 /* Fall through. */
5226 case AR_SECTION:
5227 lower = ref->u.ar.start;
5228 upper = ref->u.ar.end;
5229 break;
5231 case AR_FULL:
5232 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
5234 lower = ref->u.ar.as->lower;
5235 upper = ref->u.ar.as->upper;
5236 break;
5238 default:
5239 gcc_unreachable ();
5240 break;
5243 overflow = integer_zero_node;
5245 gfc_init_block (&set_descriptor_block);
5246 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
5247 ref->u.ar.as->corank, &offset, lower, upper,
5248 &se->pre, &set_descriptor_block, &overflow,
5249 expr3_elem_size, nelems, expr3, ts);
5251 if (dimension)
5253 var_overflow = gfc_create_var (integer_type_node, "overflow");
5254 gfc_add_modify (&se->pre, var_overflow, overflow);
5256 if (status == NULL_TREE)
5258 /* Generate the block of code handling overflow. */
5259 msg = gfc_build_addr_expr (pchar_type_node,
5260 gfc_build_localized_cstring_const
5261 ("Integer overflow when calculating the amount of "
5262 "memory to allocate"));
5263 error = build_call_expr_loc (input_location,
5264 gfor_fndecl_runtime_error, 1, msg);
5266 else
5268 tree status_type = TREE_TYPE (status);
5269 stmtblock_t set_status_block;
5271 gfc_start_block (&set_status_block);
5272 gfc_add_modify (&set_status_block, status,
5273 build_int_cst (status_type, LIBERROR_ALLOCATION));
5274 error = gfc_finish_block (&set_status_block);
5278 gfc_start_block (&elseblock);
5280 /* Allocate memory to store the data. */
5281 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
5282 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
5284 pointer = gfc_conv_descriptor_data_get (se->expr);
5285 STRIP_NOPS (pointer);
5287 if (coarray && flag_coarray == GFC_FCOARRAY_LIB)
5288 token = gfc_build_addr_expr (NULL_TREE,
5289 gfc_conv_descriptor_token (se->expr));
5291 /* The allocatable variant takes the old pointer as first argument. */
5292 if (allocatable)
5293 gfc_allocate_allocatable (&elseblock, pointer, size, token,
5294 status, errmsg, errlen, label_finish, expr);
5295 else
5296 gfc_allocate_using_malloc (&elseblock, pointer, size, status);
5298 if (dimension)
5300 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
5301 boolean_type_node, var_overflow, integer_zero_node),
5302 PRED_FORTRAN_OVERFLOW);
5303 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
5304 error, gfc_finish_block (&elseblock));
5306 else
5307 tmp = gfc_finish_block (&elseblock);
5309 gfc_add_expr_to_block (&se->pre, tmp);
5311 /* Update the array descriptors. */
5312 if (dimension)
5313 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
5315 set_descriptor = gfc_finish_block (&set_descriptor_block);
5316 if (status != NULL_TREE)
5318 cond = fold_build2_loc (input_location, EQ_EXPR,
5319 boolean_type_node, status,
5320 build_int_cst (TREE_TYPE (status), 0));
5321 gfc_add_expr_to_block (&se->pre,
5322 fold_build3_loc (input_location, COND_EXPR, void_type_node,
5323 gfc_likely (cond, PRED_FORTRAN_FAIL_ALLOC),
5324 set_descriptor,
5325 build_empty_stmt (input_location)));
5327 else
5328 gfc_add_expr_to_block (&se->pre, set_descriptor);
5330 if ((expr->ts.type == BT_DERIVED)
5331 && expr->ts.u.derived->attr.alloc_comp)
5333 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, se->expr,
5334 ref->u.ar.as->rank);
5335 gfc_add_expr_to_block (&se->pre, tmp);
5338 return true;
5342 /* Deallocate an array variable. Also used when an allocated variable goes
5343 out of scope. */
5344 /*GCC ARRAYS*/
5346 tree
5347 gfc_array_deallocate (tree descriptor, tree pstat, tree errmsg, tree errlen,
5348 tree label_finish, gfc_expr* expr)
5350 tree var;
5351 tree tmp;
5352 stmtblock_t block;
5353 bool coarray = gfc_is_coarray (expr);
5355 gfc_start_block (&block);
5357 /* Get a pointer to the data. */
5358 var = gfc_conv_descriptor_data_get (descriptor);
5359 STRIP_NOPS (var);
5361 /* Parameter is the address of the data component. */
5362 tmp = gfc_deallocate_with_status (coarray ? descriptor : var, pstat, errmsg,
5363 errlen, label_finish, false, expr, coarray);
5364 gfc_add_expr_to_block (&block, tmp);
5366 /* Zero the data pointer; only for coarrays an error can occur and then
5367 the allocation status may not be changed. */
5368 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5369 var, build_int_cst (TREE_TYPE (var), 0));
5370 if (pstat != NULL_TREE && coarray && flag_coarray == GFC_FCOARRAY_LIB)
5372 tree cond;
5373 tree stat = build_fold_indirect_ref_loc (input_location, pstat);
5375 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5376 stat, build_int_cst (TREE_TYPE (stat), 0));
5377 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5378 cond, tmp, build_empty_stmt (input_location));
5381 gfc_add_expr_to_block (&block, tmp);
5383 return gfc_finish_block (&block);
5387 /* Create an array constructor from an initialization expression.
5388 We assume the frontend already did any expansions and conversions. */
5390 tree
5391 gfc_conv_array_initializer (tree type, gfc_expr * expr)
5393 gfc_constructor *c;
5394 tree tmp;
5395 offset_int wtmp;
5396 gfc_se se;
5397 tree index, range;
5398 vec<constructor_elt, va_gc> *v = NULL;
5400 if (expr->expr_type == EXPR_VARIABLE
5401 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
5402 && expr->symtree->n.sym->value)
5403 expr = expr->symtree->n.sym->value;
5405 switch (expr->expr_type)
5407 case EXPR_CONSTANT:
5408 case EXPR_STRUCTURE:
5409 /* A single scalar or derived type value. Create an array with all
5410 elements equal to that value. */
5411 gfc_init_se (&se, NULL);
5413 if (expr->expr_type == EXPR_CONSTANT)
5414 gfc_conv_constant (&se, expr);
5415 else
5416 gfc_conv_structure (&se, expr, 1);
5418 wtmp = wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1;
5419 /* This will probably eat buckets of memory for large arrays. */
5420 while (wtmp != 0)
5422 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
5423 wtmp -= 1;
5425 break;
5427 case EXPR_ARRAY:
5428 /* Create a vector of all the elements. */
5429 for (c = gfc_constructor_first (expr->value.constructor);
5430 c; c = gfc_constructor_next (c))
5432 if (c->iterator)
5434 /* Problems occur when we get something like
5435 integer :: a(lots) = (/(i, i=1, lots)/) */
5436 gfc_fatal_error ("The number of elements in the array "
5437 "constructor at %L requires an increase of "
5438 "the allowed %d upper limit. See "
5439 "%<-fmax-array-constructor%> option",
5440 &expr->where, flag_max_array_constructor);
5441 return NULL_TREE;
5443 if (mpz_cmp_si (c->offset, 0) != 0)
5444 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5445 else
5446 index = NULL_TREE;
5448 if (mpz_cmp_si (c->repeat, 1) > 0)
5450 tree tmp1, tmp2;
5451 mpz_t maxval;
5453 mpz_init (maxval);
5454 mpz_add (maxval, c->offset, c->repeat);
5455 mpz_sub_ui (maxval, maxval, 1);
5456 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5457 if (mpz_cmp_si (c->offset, 0) != 0)
5459 mpz_add_ui (maxval, c->offset, 1);
5460 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5462 else
5463 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5465 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
5466 mpz_clear (maxval);
5468 else
5469 range = NULL;
5471 gfc_init_se (&se, NULL);
5472 switch (c->expr->expr_type)
5474 case EXPR_CONSTANT:
5475 gfc_conv_constant (&se, c->expr);
5476 break;
5478 case EXPR_STRUCTURE:
5479 gfc_conv_structure (&se, c->expr, 1);
5480 break;
5482 default:
5483 /* Catch those occasional beasts that do not simplify
5484 for one reason or another, assuming that if they are
5485 standard defying the frontend will catch them. */
5486 gfc_conv_expr (&se, c->expr);
5487 break;
5490 if (range == NULL_TREE)
5491 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5492 else
5494 if (index != NULL_TREE)
5495 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5496 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
5499 break;
5501 case EXPR_NULL:
5502 return gfc_build_null_descriptor (type);
5504 default:
5505 gcc_unreachable ();
5508 /* Create a constructor from the list of elements. */
5509 tmp = build_constructor (type, v);
5510 TREE_CONSTANT (tmp) = 1;
5511 return tmp;
5515 /* Generate code to evaluate non-constant coarray cobounds. */
5517 void
5518 gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
5519 const gfc_symbol *sym)
5521 int dim;
5522 tree ubound;
5523 tree lbound;
5524 gfc_se se;
5525 gfc_array_spec *as;
5527 as = sym->as;
5529 for (dim = as->rank; dim < as->rank + as->corank; dim++)
5531 /* Evaluate non-constant array bound expressions. */
5532 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
5533 if (as->lower[dim] && !INTEGER_CST_P (lbound))
5535 gfc_init_se (&se, NULL);
5536 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
5537 gfc_add_block_to_block (pblock, &se.pre);
5538 gfc_add_modify (pblock, lbound, se.expr);
5540 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
5541 if (as->upper[dim] && !INTEGER_CST_P (ubound))
5543 gfc_init_se (&se, NULL);
5544 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
5545 gfc_add_block_to_block (pblock, &se.pre);
5546 gfc_add_modify (pblock, ubound, se.expr);
5552 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
5553 returns the size (in elements) of the array. */
5555 static tree
5556 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
5557 stmtblock_t * pblock)
5559 gfc_array_spec *as;
5560 tree size;
5561 tree stride;
5562 tree offset;
5563 tree ubound;
5564 tree lbound;
5565 tree tmp;
5566 gfc_se se;
5568 int dim;
5570 as = sym->as;
5572 size = gfc_index_one_node;
5573 offset = gfc_index_zero_node;
5574 for (dim = 0; dim < as->rank; dim++)
5576 /* Evaluate non-constant array bound expressions. */
5577 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
5578 if (as->lower[dim] && !INTEGER_CST_P (lbound))
5580 gfc_init_se (&se, NULL);
5581 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
5582 gfc_add_block_to_block (pblock, &se.pre);
5583 gfc_add_modify (pblock, lbound, se.expr);
5585 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
5586 if (as->upper[dim] && !INTEGER_CST_P (ubound))
5588 gfc_init_se (&se, NULL);
5589 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
5590 gfc_add_block_to_block (pblock, &se.pre);
5591 gfc_add_modify (pblock, ubound, se.expr);
5593 /* The offset of this dimension. offset = offset - lbound * stride. */
5594 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5595 lbound, size);
5596 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5597 offset, tmp);
5599 /* The size of this dimension, and the stride of the next. */
5600 if (dim + 1 < as->rank)
5601 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
5602 else
5603 stride = GFC_TYPE_ARRAY_SIZE (type);
5605 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
5607 /* Calculate stride = size * (ubound + 1 - lbound). */
5608 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5609 gfc_array_index_type,
5610 gfc_index_one_node, lbound);
5611 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5612 gfc_array_index_type, ubound, tmp);
5613 tmp = fold_build2_loc (input_location, MULT_EXPR,
5614 gfc_array_index_type, size, tmp);
5615 if (stride)
5616 gfc_add_modify (pblock, stride, tmp);
5617 else
5618 stride = gfc_evaluate_now (tmp, pblock);
5620 /* Make sure that negative size arrays are translated
5621 to being zero size. */
5622 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
5623 stride, gfc_index_zero_node);
5624 tmp = fold_build3_loc (input_location, COND_EXPR,
5625 gfc_array_index_type, tmp,
5626 stride, gfc_index_zero_node);
5627 gfc_add_modify (pblock, stride, tmp);
5630 size = stride;
5633 gfc_trans_array_cobounds (type, pblock, sym);
5634 gfc_trans_vla_type_sizes (sym, pblock);
5636 *poffset = offset;
5637 return size;
5641 /* Generate code to initialize/allocate an array variable. */
5643 void
5644 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
5645 gfc_wrapped_block * block)
5647 stmtblock_t init;
5648 tree type;
5649 tree tmp = NULL_TREE;
5650 tree size;
5651 tree offset;
5652 tree space;
5653 tree inittree;
5654 bool onstack;
5656 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
5658 /* Do nothing for USEd variables. */
5659 if (sym->attr.use_assoc)
5660 return;
5662 type = TREE_TYPE (decl);
5663 gcc_assert (GFC_ARRAY_TYPE_P (type));
5664 onstack = TREE_CODE (type) != POINTER_TYPE;
5666 gfc_init_block (&init);
5668 /* Evaluate character string length. */
5669 if (sym->ts.type == BT_CHARACTER
5670 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
5672 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5674 gfc_trans_vla_type_sizes (sym, &init);
5676 /* Emit a DECL_EXPR for this variable, which will cause the
5677 gimplifier to allocate storage, and all that good stuff. */
5678 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
5679 gfc_add_expr_to_block (&init, tmp);
5682 if (onstack)
5684 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5685 return;
5688 type = TREE_TYPE (type);
5690 gcc_assert (!sym->attr.use_assoc);
5691 gcc_assert (!TREE_STATIC (decl));
5692 gcc_assert (!sym->module);
5694 if (sym->ts.type == BT_CHARACTER
5695 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
5696 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5698 size = gfc_trans_array_bounds (type, sym, &offset, &init);
5700 /* Don't actually allocate space for Cray Pointees. */
5701 if (sym->attr.cray_pointee)
5703 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5704 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5706 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5707 return;
5710 if (flag_stack_arrays)
5712 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
5713 space = build_decl (sym->declared_at.lb->location,
5714 VAR_DECL, create_tmp_var_name ("A"),
5715 TREE_TYPE (TREE_TYPE (decl)));
5716 gfc_trans_vla_type_sizes (sym, &init);
5718 else
5720 /* The size is the number of elements in the array, so multiply by the
5721 size of an element to get the total size. */
5722 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5723 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5724 size, fold_convert (gfc_array_index_type, tmp));
5726 /* Allocate memory to hold the data. */
5727 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
5728 gfc_add_modify (&init, decl, tmp);
5730 /* Free the temporary. */
5731 tmp = gfc_call_free (convert (pvoid_type_node, decl));
5732 space = NULL_TREE;
5735 /* Set offset of the array. */
5736 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5737 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5739 /* Automatic arrays should not have initializers. */
5740 gcc_assert (!sym->value);
5742 inittree = gfc_finish_block (&init);
5744 if (space)
5746 tree addr;
5747 pushdecl (space);
5749 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
5750 where also space is located. */
5751 gfc_init_block (&init);
5752 tmp = fold_build1_loc (input_location, DECL_EXPR,
5753 TREE_TYPE (space), space);
5754 gfc_add_expr_to_block (&init, tmp);
5755 addr = fold_build1_loc (sym->declared_at.lb->location,
5756 ADDR_EXPR, TREE_TYPE (decl), space);
5757 gfc_add_modify (&init, decl, addr);
5758 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5759 tmp = NULL_TREE;
5761 gfc_add_init_cleanup (block, inittree, tmp);
5765 /* Generate entry and exit code for g77 calling convention arrays. */
5767 void
5768 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
5770 tree parm;
5771 tree type;
5772 locus loc;
5773 tree offset;
5774 tree tmp;
5775 tree stmt;
5776 stmtblock_t init;
5778 gfc_save_backend_locus (&loc);
5779 gfc_set_backend_locus (&sym->declared_at);
5781 /* Descriptor type. */
5782 parm = sym->backend_decl;
5783 type = TREE_TYPE (parm);
5784 gcc_assert (GFC_ARRAY_TYPE_P (type));
5786 gfc_start_block (&init);
5788 if (sym->ts.type == BT_CHARACTER
5789 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
5790 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5792 /* Evaluate the bounds of the array. */
5793 gfc_trans_array_bounds (type, sym, &offset, &init);
5795 /* Set the offset. */
5796 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5797 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5799 /* Set the pointer itself if we aren't using the parameter directly. */
5800 if (TREE_CODE (parm) != PARM_DECL)
5802 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
5803 gfc_add_modify (&init, parm, tmp);
5805 stmt = gfc_finish_block (&init);
5807 gfc_restore_backend_locus (&loc);
5809 /* Add the initialization code to the start of the function. */
5811 if (sym->attr.optional || sym->attr.not_always_present)
5813 tmp = gfc_conv_expr_present (sym);
5814 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
5817 gfc_add_init_cleanup (block, stmt, NULL_TREE);
5821 /* Modify the descriptor of an array parameter so that it has the
5822 correct lower bound. Also move the upper bound accordingly.
5823 If the array is not packed, it will be copied into a temporary.
5824 For each dimension we set the new lower and upper bounds. Then we copy the
5825 stride and calculate the offset for this dimension. We also work out
5826 what the stride of a packed array would be, and see it the two match.
5827 If the array need repacking, we set the stride to the values we just
5828 calculated, recalculate the offset and copy the array data.
5829 Code is also added to copy the data back at the end of the function.
5832 void
5833 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
5834 gfc_wrapped_block * block)
5836 tree size;
5837 tree type;
5838 tree offset;
5839 locus loc;
5840 stmtblock_t init;
5841 tree stmtInit, stmtCleanup;
5842 tree lbound;
5843 tree ubound;
5844 tree dubound;
5845 tree dlbound;
5846 tree dumdesc;
5847 tree tmp;
5848 tree stride, stride2;
5849 tree stmt_packed;
5850 tree stmt_unpacked;
5851 tree partial;
5852 gfc_se se;
5853 int n;
5854 int checkparm;
5855 int no_repack;
5856 bool optional_arg;
5858 /* Do nothing for pointer and allocatable arrays. */
5859 if (sym->attr.pointer || sym->attr.allocatable)
5860 return;
5862 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
5864 gfc_trans_g77_array (sym, block);
5865 return;
5868 gfc_save_backend_locus (&loc);
5869 gfc_set_backend_locus (&sym->declared_at);
5871 /* Descriptor type. */
5872 type = TREE_TYPE (tmpdesc);
5873 gcc_assert (GFC_ARRAY_TYPE_P (type));
5874 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5875 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
5876 gfc_start_block (&init);
5878 if (sym->ts.type == BT_CHARACTER
5879 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
5880 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5882 checkparm = (sym->as->type == AS_EXPLICIT
5883 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
5885 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
5886 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
5888 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
5890 /* For non-constant shape arrays we only check if the first dimension
5891 is contiguous. Repacking higher dimensions wouldn't gain us
5892 anything as we still don't know the array stride. */
5893 partial = gfc_create_var (boolean_type_node, "partial");
5894 TREE_USED (partial) = 1;
5895 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
5896 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, tmp,
5897 gfc_index_one_node);
5898 gfc_add_modify (&init, partial, tmp);
5900 else
5901 partial = NULL_TREE;
5903 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
5904 here, however I think it does the right thing. */
5905 if (no_repack)
5907 /* Set the first stride. */
5908 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
5909 stride = gfc_evaluate_now (stride, &init);
5911 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5912 stride, gfc_index_zero_node);
5913 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
5914 tmp, gfc_index_one_node, stride);
5915 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
5916 gfc_add_modify (&init, stride, tmp);
5918 /* Allow the user to disable array repacking. */
5919 stmt_unpacked = NULL_TREE;
5921 else
5923 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
5924 /* A library call to repack the array if necessary. */
5925 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5926 stmt_unpacked = build_call_expr_loc (input_location,
5927 gfor_fndecl_in_pack, 1, tmp);
5929 stride = gfc_index_one_node;
5931 if (warn_array_temporaries)
5932 gfc_warning (OPT_Warray_temporaries,
5933 "Creating array temporary at %L", &loc);
5936 /* This is for the case where the array data is used directly without
5937 calling the repack function. */
5938 if (no_repack || partial != NULL_TREE)
5939 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
5940 else
5941 stmt_packed = NULL_TREE;
5943 /* Assign the data pointer. */
5944 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
5946 /* Don't repack unknown shape arrays when the first stride is 1. */
5947 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
5948 partial, stmt_packed, stmt_unpacked);
5950 else
5951 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
5952 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
5954 offset = gfc_index_zero_node;
5955 size = gfc_index_one_node;
5957 /* Evaluate the bounds of the array. */
5958 for (n = 0; n < sym->as->rank; n++)
5960 if (checkparm || !sym->as->upper[n])
5962 /* Get the bounds of the actual parameter. */
5963 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
5964 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
5966 else
5968 dubound = NULL_TREE;
5969 dlbound = NULL_TREE;
5972 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
5973 if (!INTEGER_CST_P (lbound))
5975 gfc_init_se (&se, NULL);
5976 gfc_conv_expr_type (&se, sym->as->lower[n],
5977 gfc_array_index_type);
5978 gfc_add_block_to_block (&init, &se.pre);
5979 gfc_add_modify (&init, lbound, se.expr);
5982 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
5983 /* Set the desired upper bound. */
5984 if (sym->as->upper[n])
5986 /* We know what we want the upper bound to be. */
5987 if (!INTEGER_CST_P (ubound))
5989 gfc_init_se (&se, NULL);
5990 gfc_conv_expr_type (&se, sym->as->upper[n],
5991 gfc_array_index_type);
5992 gfc_add_block_to_block (&init, &se.pre);
5993 gfc_add_modify (&init, ubound, se.expr);
5996 /* Check the sizes match. */
5997 if (checkparm)
5999 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
6000 char * msg;
6001 tree temp;
6003 temp = fold_build2_loc (input_location, MINUS_EXPR,
6004 gfc_array_index_type, ubound, lbound);
6005 temp = fold_build2_loc (input_location, PLUS_EXPR,
6006 gfc_array_index_type,
6007 gfc_index_one_node, temp);
6008 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
6009 gfc_array_index_type, dubound,
6010 dlbound);
6011 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
6012 gfc_array_index_type,
6013 gfc_index_one_node, stride2);
6014 tmp = fold_build2_loc (input_location, NE_EXPR,
6015 gfc_array_index_type, temp, stride2);
6016 msg = xasprintf ("Dimension %d of array '%s' has extent "
6017 "%%ld instead of %%ld", n+1, sym->name);
6019 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
6020 fold_convert (long_integer_type_node, temp),
6021 fold_convert (long_integer_type_node, stride2));
6023 free (msg);
6026 else
6028 /* For assumed shape arrays move the upper bound by the same amount
6029 as the lower bound. */
6030 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6031 gfc_array_index_type, dubound, dlbound);
6032 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6033 gfc_array_index_type, tmp, lbound);
6034 gfc_add_modify (&init, ubound, tmp);
6036 /* The offset of this dimension. offset = offset - lbound * stride. */
6037 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6038 lbound, stride);
6039 offset = fold_build2_loc (input_location, MINUS_EXPR,
6040 gfc_array_index_type, offset, tmp);
6042 /* The size of this dimension, and the stride of the next. */
6043 if (n + 1 < sym->as->rank)
6045 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
6047 if (no_repack || partial != NULL_TREE)
6048 stmt_unpacked =
6049 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
6051 /* Figure out the stride if not a known constant. */
6052 if (!INTEGER_CST_P (stride))
6054 if (no_repack)
6055 stmt_packed = NULL_TREE;
6056 else
6058 /* Calculate stride = size * (ubound + 1 - lbound). */
6059 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6060 gfc_array_index_type,
6061 gfc_index_one_node, lbound);
6062 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6063 gfc_array_index_type, ubound, tmp);
6064 size = fold_build2_loc (input_location, MULT_EXPR,
6065 gfc_array_index_type, size, tmp);
6066 stmt_packed = size;
6069 /* Assign the stride. */
6070 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6071 tmp = fold_build3_loc (input_location, COND_EXPR,
6072 gfc_array_index_type, partial,
6073 stmt_unpacked, stmt_packed);
6074 else
6075 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
6076 gfc_add_modify (&init, stride, tmp);
6079 else
6081 stride = GFC_TYPE_ARRAY_SIZE (type);
6083 if (stride && !INTEGER_CST_P (stride))
6085 /* Calculate size = stride * (ubound + 1 - lbound). */
6086 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6087 gfc_array_index_type,
6088 gfc_index_one_node, lbound);
6089 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6090 gfc_array_index_type,
6091 ubound, tmp);
6092 tmp = fold_build2_loc (input_location, MULT_EXPR,
6093 gfc_array_index_type,
6094 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
6095 gfc_add_modify (&init, stride, tmp);
6100 gfc_trans_array_cobounds (type, &init, sym);
6102 /* Set the offset. */
6103 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
6104 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6106 gfc_trans_vla_type_sizes (sym, &init);
6108 stmtInit = gfc_finish_block (&init);
6110 /* Only do the entry/initialization code if the arg is present. */
6111 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6112 optional_arg = (sym->attr.optional
6113 || (sym->ns->proc_name->attr.entry_master
6114 && sym->attr.dummy));
6115 if (optional_arg)
6117 tmp = gfc_conv_expr_present (sym);
6118 stmtInit = build3_v (COND_EXPR, tmp, stmtInit,
6119 build_empty_stmt (input_location));
6122 /* Cleanup code. */
6123 if (no_repack)
6124 stmtCleanup = NULL_TREE;
6125 else
6127 stmtblock_t cleanup;
6128 gfc_start_block (&cleanup);
6130 if (sym->attr.intent != INTENT_IN)
6132 /* Copy the data back. */
6133 tmp = build_call_expr_loc (input_location,
6134 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
6135 gfc_add_expr_to_block (&cleanup, tmp);
6138 /* Free the temporary. */
6139 tmp = gfc_call_free (tmpdesc);
6140 gfc_add_expr_to_block (&cleanup, tmp);
6142 stmtCleanup = gfc_finish_block (&cleanup);
6144 /* Only do the cleanup if the array was repacked. */
6145 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
6146 tmp = gfc_conv_descriptor_data_get (tmp);
6147 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6148 tmp, tmpdesc);
6149 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6150 build_empty_stmt (input_location));
6152 if (optional_arg)
6154 tmp = gfc_conv_expr_present (sym);
6155 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6156 build_empty_stmt (input_location));
6160 /* We don't need to free any memory allocated by internal_pack as it will
6161 be freed at the end of the function by pop_context. */
6162 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
6164 gfc_restore_backend_locus (&loc);
6168 /* Calculate the overall offset, including subreferences. */
6169 static void
6170 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
6171 bool subref, gfc_expr *expr)
6173 tree tmp;
6174 tree field;
6175 tree stride;
6176 tree index;
6177 gfc_ref *ref;
6178 gfc_se start;
6179 int n;
6181 /* If offset is NULL and this is not a subreferenced array, there is
6182 nothing to do. */
6183 if (offset == NULL_TREE)
6185 if (subref)
6186 offset = gfc_index_zero_node;
6187 else
6188 return;
6191 tmp = build_array_ref (desc, offset, NULL);
6193 /* Offset the data pointer for pointer assignments from arrays with
6194 subreferences; e.g. my_integer => my_type(:)%integer_component. */
6195 if (subref)
6197 /* Go past the array reference. */
6198 for (ref = expr->ref; ref; ref = ref->next)
6199 if (ref->type == REF_ARRAY &&
6200 ref->u.ar.type != AR_ELEMENT)
6202 ref = ref->next;
6203 break;
6206 /* Calculate the offset for each subsequent subreference. */
6207 for (; ref; ref = ref->next)
6209 switch (ref->type)
6211 case REF_COMPONENT:
6212 field = ref->u.c.component->backend_decl;
6213 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6214 tmp = fold_build3_loc (input_location, COMPONENT_REF,
6215 TREE_TYPE (field),
6216 tmp, field, NULL_TREE);
6217 break;
6219 case REF_SUBSTRING:
6220 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
6221 gfc_init_se (&start, NULL);
6222 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
6223 gfc_add_block_to_block (block, &start.pre);
6224 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
6225 break;
6227 case REF_ARRAY:
6228 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
6229 && ref->u.ar.type == AR_ELEMENT);
6231 /* TODO - Add bounds checking. */
6232 stride = gfc_index_one_node;
6233 index = gfc_index_zero_node;
6234 for (n = 0; n < ref->u.ar.dimen; n++)
6236 tree itmp;
6237 tree jtmp;
6239 /* Update the index. */
6240 gfc_init_se (&start, NULL);
6241 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
6242 itmp = gfc_evaluate_now (start.expr, block);
6243 gfc_init_se (&start, NULL);
6244 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
6245 jtmp = gfc_evaluate_now (start.expr, block);
6246 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6247 gfc_array_index_type, itmp, jtmp);
6248 itmp = fold_build2_loc (input_location, MULT_EXPR,
6249 gfc_array_index_type, itmp, stride);
6250 index = fold_build2_loc (input_location, PLUS_EXPR,
6251 gfc_array_index_type, itmp, index);
6252 index = gfc_evaluate_now (index, block);
6254 /* Update the stride. */
6255 gfc_init_se (&start, NULL);
6256 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
6257 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6258 gfc_array_index_type, start.expr,
6259 jtmp);
6260 itmp = fold_build2_loc (input_location, PLUS_EXPR,
6261 gfc_array_index_type,
6262 gfc_index_one_node, itmp);
6263 stride = fold_build2_loc (input_location, MULT_EXPR,
6264 gfc_array_index_type, stride, itmp);
6265 stride = gfc_evaluate_now (stride, block);
6268 /* Apply the index to obtain the array element. */
6269 tmp = gfc_build_array_ref (tmp, index, NULL);
6270 break;
6272 default:
6273 gcc_unreachable ();
6274 break;
6279 /* Set the target data pointer. */
6280 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
6281 gfc_conv_descriptor_data_set (block, parm, offset);
6285 /* gfc_conv_expr_descriptor needs the string length an expression
6286 so that the size of the temporary can be obtained. This is done
6287 by adding up the string lengths of all the elements in the
6288 expression. Function with non-constant expressions have their
6289 string lengths mapped onto the actual arguments using the
6290 interface mapping machinery in trans-expr.c. */
6291 static void
6292 get_array_charlen (gfc_expr *expr, gfc_se *se)
6294 gfc_interface_mapping mapping;
6295 gfc_formal_arglist *formal;
6296 gfc_actual_arglist *arg;
6297 gfc_se tse;
6299 if (expr->ts.u.cl->length
6300 && gfc_is_constant_expr (expr->ts.u.cl->length))
6302 if (!expr->ts.u.cl->backend_decl)
6303 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6304 return;
6307 switch (expr->expr_type)
6309 case EXPR_OP:
6310 get_array_charlen (expr->value.op.op1, se);
6312 /* For parentheses the expression ts.u.cl is identical. */
6313 if (expr->value.op.op == INTRINSIC_PARENTHESES)
6314 return;
6316 expr->ts.u.cl->backend_decl =
6317 gfc_create_var (gfc_charlen_type_node, "sln");
6319 if (expr->value.op.op2)
6321 get_array_charlen (expr->value.op.op2, se);
6323 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
6325 /* Add the string lengths and assign them to the expression
6326 string length backend declaration. */
6327 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6328 fold_build2_loc (input_location, PLUS_EXPR,
6329 gfc_charlen_type_node,
6330 expr->value.op.op1->ts.u.cl->backend_decl,
6331 expr->value.op.op2->ts.u.cl->backend_decl));
6333 else
6334 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6335 expr->value.op.op1->ts.u.cl->backend_decl);
6336 break;
6338 case EXPR_FUNCTION:
6339 if (expr->value.function.esym == NULL
6340 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
6342 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6343 break;
6346 /* Map expressions involving the dummy arguments onto the actual
6347 argument expressions. */
6348 gfc_init_interface_mapping (&mapping);
6349 formal = gfc_sym_get_dummy_args (expr->symtree->n.sym);
6350 arg = expr->value.function.actual;
6352 /* Set se = NULL in the calls to the interface mapping, to suppress any
6353 backend stuff. */
6354 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
6356 if (!arg->expr)
6357 continue;
6358 if (formal->sym)
6359 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
6362 gfc_init_se (&tse, NULL);
6364 /* Build the expression for the character length and convert it. */
6365 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
6367 gfc_add_block_to_block (&se->pre, &tse.pre);
6368 gfc_add_block_to_block (&se->post, &tse.post);
6369 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
6370 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
6371 gfc_charlen_type_node, tse.expr,
6372 build_int_cst (gfc_charlen_type_node, 0));
6373 expr->ts.u.cl->backend_decl = tse.expr;
6374 gfc_free_interface_mapping (&mapping);
6375 break;
6377 default:
6378 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6379 break;
6384 /* Helper function to check dimensions. */
6385 static bool
6386 transposed_dims (gfc_ss *ss)
6388 int n;
6390 for (n = 0; n < ss->dimen; n++)
6391 if (ss->dim[n] != n)
6392 return true;
6393 return false;
6397 /* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
6398 AR_FULL, suitable for the scalarizer. */
6400 static gfc_ss *
6401 walk_coarray (gfc_expr *e)
6403 gfc_ss *ss;
6405 gcc_assert (gfc_get_corank (e) > 0);
6407 ss = gfc_walk_expr (e);
6409 /* Fix scalar coarray. */
6410 if (ss == gfc_ss_terminator)
6412 gfc_ref *ref;
6414 ref = e->ref;
6415 while (ref)
6417 if (ref->type == REF_ARRAY
6418 && ref->u.ar.codimen > 0)
6419 break;
6421 ref = ref->next;
6424 gcc_assert (ref != NULL);
6425 if (ref->u.ar.type == AR_ELEMENT)
6426 ref->u.ar.type = AR_SECTION;
6427 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
6430 return ss;
6434 /* Convert an array for passing as an actual argument. Expressions and
6435 vector subscripts are evaluated and stored in a temporary, which is then
6436 passed. For whole arrays the descriptor is passed. For array sections
6437 a modified copy of the descriptor is passed, but using the original data.
6439 This function is also used for array pointer assignments, and there
6440 are three cases:
6442 - se->want_pointer && !se->direct_byref
6443 EXPR is an actual argument. On exit, se->expr contains a
6444 pointer to the array descriptor.
6446 - !se->want_pointer && !se->direct_byref
6447 EXPR is an actual argument to an intrinsic function or the
6448 left-hand side of a pointer assignment. On exit, se->expr
6449 contains the descriptor for EXPR.
6451 - !se->want_pointer && se->direct_byref
6452 EXPR is the right-hand side of a pointer assignment and
6453 se->expr is the descriptor for the previously-evaluated
6454 left-hand side. The function creates an assignment from
6455 EXPR to se->expr.
6458 The se->force_tmp flag disables the non-copying descriptor optimization
6459 that is used for transpose. It may be used in cases where there is an
6460 alias between the transpose argument and another argument in the same
6461 function call. */
6463 void
6464 gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
6466 gfc_ss *ss;
6467 gfc_ss_type ss_type;
6468 gfc_ss_info *ss_info;
6469 gfc_loopinfo loop;
6470 gfc_array_info *info;
6471 int need_tmp;
6472 int n;
6473 tree tmp;
6474 tree desc;
6475 stmtblock_t block;
6476 tree start;
6477 tree offset;
6478 int full;
6479 bool subref_array_target = false;
6480 gfc_expr *arg, *ss_expr;
6482 if (se->want_coarray)
6483 ss = walk_coarray (expr);
6484 else
6485 ss = gfc_walk_expr (expr);
6487 gcc_assert (ss != NULL);
6488 gcc_assert (ss != gfc_ss_terminator);
6490 ss_info = ss->info;
6491 ss_type = ss_info->type;
6492 ss_expr = ss_info->expr;
6494 /* Special case: TRANSPOSE which needs no temporary. */
6495 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
6496 && NULL != (arg = gfc_get_noncopying_intrinsic_argument (expr)))
6498 /* This is a call to transpose which has already been handled by the
6499 scalarizer, so that we just need to get its argument's descriptor. */
6500 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
6501 expr = expr->value.function.actual->expr;
6504 /* Special case things we know we can pass easily. */
6505 switch (expr->expr_type)
6507 case EXPR_VARIABLE:
6508 /* If we have a linear array section, we can pass it directly.
6509 Otherwise we need to copy it into a temporary. */
6511 gcc_assert (ss_type == GFC_SS_SECTION);
6512 gcc_assert (ss_expr == expr);
6513 info = &ss_info->data.array;
6515 /* Get the descriptor for the array. */
6516 gfc_conv_ss_descriptor (&se->pre, ss, 0);
6517 desc = info->descriptor;
6519 subref_array_target = se->direct_byref && is_subref_array (expr);
6520 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
6521 && !subref_array_target;
6523 if (se->force_tmp)
6524 need_tmp = 1;
6526 if (need_tmp)
6527 full = 0;
6528 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6530 /* Create a new descriptor if the array doesn't have one. */
6531 full = 0;
6533 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
6534 full = 1;
6535 else if (se->direct_byref)
6536 full = 0;
6537 else
6538 full = gfc_full_array_ref_p (info->ref, NULL);
6540 if (full && !transposed_dims (ss))
6542 if (se->direct_byref && !se->byref_noassign)
6544 /* Copy the descriptor for pointer assignments. */
6545 gfc_add_modify (&se->pre, se->expr, desc);
6547 /* Add any offsets from subreferences. */
6548 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
6549 subref_array_target, expr);
6551 else if (se->want_pointer)
6553 /* We pass full arrays directly. This means that pointers and
6554 allocatable arrays should also work. */
6555 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6557 else
6559 se->expr = desc;
6562 if (expr->ts.type == BT_CHARACTER)
6563 se->string_length = gfc_get_expr_charlen (expr);
6565 gfc_free_ss_chain (ss);
6566 return;
6568 break;
6570 case EXPR_FUNCTION:
6571 /* A transformational function return value will be a temporary
6572 array descriptor. We still need to go through the scalarizer
6573 to create the descriptor. Elemental functions are handled as
6574 arbitrary expressions, i.e. copy to a temporary. */
6576 if (se->direct_byref)
6578 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
6580 /* For pointer assignments pass the descriptor directly. */
6581 if (se->ss == NULL)
6582 se->ss = ss;
6583 else
6584 gcc_assert (se->ss == ss);
6585 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
6586 gfc_conv_expr (se, expr);
6587 gfc_free_ss_chain (ss);
6588 return;
6591 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
6593 if (ss_expr != expr)
6594 /* Elemental function. */
6595 gcc_assert ((expr->value.function.esym != NULL
6596 && expr->value.function.esym->attr.elemental)
6597 || (expr->value.function.isym != NULL
6598 && expr->value.function.isym->elemental)
6599 || gfc_inline_intrinsic_function_p (expr));
6600 else
6601 gcc_assert (ss_type == GFC_SS_INTRINSIC);
6603 need_tmp = 1;
6604 if (expr->ts.type == BT_CHARACTER
6605 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6606 get_array_charlen (expr, se);
6608 info = NULL;
6610 else
6612 /* Transformational function. */
6613 info = &ss_info->data.array;
6614 need_tmp = 0;
6616 break;
6618 case EXPR_ARRAY:
6619 /* Constant array constructors don't need a temporary. */
6620 if (ss_type == GFC_SS_CONSTRUCTOR
6621 && expr->ts.type != BT_CHARACTER
6622 && gfc_constant_array_constructor_p (expr->value.constructor))
6624 need_tmp = 0;
6625 info = &ss_info->data.array;
6627 else
6629 need_tmp = 1;
6630 info = NULL;
6632 break;
6634 default:
6635 /* Something complicated. Copy it into a temporary. */
6636 need_tmp = 1;
6637 info = NULL;
6638 break;
6641 /* If we are creating a temporary, we don't need to bother about aliases
6642 anymore. */
6643 if (need_tmp)
6644 se->force_tmp = 0;
6646 gfc_init_loopinfo (&loop);
6648 /* Associate the SS with the loop. */
6649 gfc_add_ss_to_loop (&loop, ss);
6651 /* Tell the scalarizer not to bother creating loop variables, etc. */
6652 if (!need_tmp)
6653 loop.array_parameter = 1;
6654 else
6655 /* The right-hand side of a pointer assignment mustn't use a temporary. */
6656 gcc_assert (!se->direct_byref);
6658 /* Setup the scalarizing loops and bounds. */
6659 gfc_conv_ss_startstride (&loop);
6661 if (need_tmp)
6663 if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
6664 get_array_charlen (expr, se);
6666 /* Tell the scalarizer to make a temporary. */
6667 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
6668 ((expr->ts.type == BT_CHARACTER)
6669 ? expr->ts.u.cl->backend_decl
6670 : NULL),
6671 loop.dimen);
6673 se->string_length = loop.temp_ss->info->string_length;
6674 gcc_assert (loop.temp_ss->dimen == loop.dimen);
6675 gfc_add_ss_to_loop (&loop, loop.temp_ss);
6678 gfc_conv_loop_setup (&loop, & expr->where);
6680 if (need_tmp)
6682 /* Copy into a temporary and pass that. We don't need to copy the data
6683 back because expressions and vector subscripts must be INTENT_IN. */
6684 /* TODO: Optimize passing function return values. */
6685 gfc_se lse;
6686 gfc_se rse;
6688 /* Start the copying loops. */
6689 gfc_mark_ss_chain_used (loop.temp_ss, 1);
6690 gfc_mark_ss_chain_used (ss, 1);
6691 gfc_start_scalarized_body (&loop, &block);
6693 /* Copy each data element. */
6694 gfc_init_se (&lse, NULL);
6695 gfc_copy_loopinfo_to_se (&lse, &loop);
6696 gfc_init_se (&rse, NULL);
6697 gfc_copy_loopinfo_to_se (&rse, &loop);
6699 lse.ss = loop.temp_ss;
6700 rse.ss = ss;
6702 gfc_conv_scalarized_array_ref (&lse, NULL);
6703 if (expr->ts.type == BT_CHARACTER)
6705 gfc_conv_expr (&rse, expr);
6706 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
6707 rse.expr = build_fold_indirect_ref_loc (input_location,
6708 rse.expr);
6710 else
6711 gfc_conv_expr_val (&rse, expr);
6713 gfc_add_block_to_block (&block, &rse.pre);
6714 gfc_add_block_to_block (&block, &lse.pre);
6716 lse.string_length = rse.string_length;
6717 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
6718 expr->expr_type == EXPR_VARIABLE
6719 || expr->expr_type == EXPR_ARRAY, true);
6720 gfc_add_expr_to_block (&block, tmp);
6722 /* Finish the copying loops. */
6723 gfc_trans_scalarizing_loops (&loop, &block);
6725 desc = loop.temp_ss->info->data.array.descriptor;
6727 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
6729 desc = info->descriptor;
6730 se->string_length = ss_info->string_length;
6732 else
6734 /* We pass sections without copying to a temporary. Make a new
6735 descriptor and point it at the section we want. The loop variable
6736 limits will be the limits of the section.
6737 A function may decide to repack the array to speed up access, but
6738 we're not bothered about that here. */
6739 int dim, ndim, codim;
6740 tree parm;
6741 tree parmtype;
6742 tree stride;
6743 tree from;
6744 tree to;
6745 tree base;
6747 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
6749 if (se->want_coarray)
6751 gfc_array_ref *ar = &info->ref->u.ar;
6753 codim = gfc_get_corank (expr);
6754 for (n = 0; n < codim - 1; n++)
6756 /* Make sure we are not lost somehow. */
6757 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
6759 /* Make sure the call to gfc_conv_section_startstride won't
6760 generate unnecessary code to calculate stride. */
6761 gcc_assert (ar->stride[n + ndim] == NULL);
6763 gfc_conv_section_startstride (&loop.pre, ss, n + ndim);
6764 loop.from[n + loop.dimen] = info->start[n + ndim];
6765 loop.to[n + loop.dimen] = info->end[n + ndim];
6768 gcc_assert (n == codim - 1);
6769 evaluate_bound (&loop.pre, info->start, ar->start,
6770 info->descriptor, n + ndim, true);
6771 loop.from[n + loop.dimen] = info->start[n + ndim];
6773 else
6774 codim = 0;
6776 /* Set the string_length for a character array. */
6777 if (expr->ts.type == BT_CHARACTER)
6778 se->string_length = gfc_get_expr_charlen (expr);
6780 desc = info->descriptor;
6781 if (se->direct_byref && !se->byref_noassign)
6783 /* For pointer assignments we fill in the destination. */
6784 parm = se->expr;
6785 parmtype = TREE_TYPE (parm);
6787 else
6789 /* Otherwise make a new one. */
6790 parmtype = gfc_get_element_type (TREE_TYPE (desc));
6791 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
6792 loop.from, loop.to, 0,
6793 GFC_ARRAY_UNKNOWN, false);
6794 parm = gfc_create_var (parmtype, "parm");
6797 offset = gfc_index_zero_node;
6799 /* The following can be somewhat confusing. We have two
6800 descriptors, a new one and the original array.
6801 {parm, parmtype, dim} refer to the new one.
6802 {desc, type, n, loop} refer to the original, which maybe
6803 a descriptorless array.
6804 The bounds of the scalarization are the bounds of the section.
6805 We don't have to worry about numeric overflows when calculating
6806 the offsets because all elements are within the array data. */
6808 /* Set the dtype. */
6809 tmp = gfc_conv_descriptor_dtype (parm);
6810 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
6812 /* Set offset for assignments to pointer only to zero if it is not
6813 the full array. */
6814 if ((se->direct_byref || se->use_offset)
6815 && ((info->ref && info->ref->u.ar.type != AR_FULL)
6816 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
6817 base = gfc_index_zero_node;
6818 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6819 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
6820 else
6821 base = NULL_TREE;
6823 for (n = 0; n < ndim; n++)
6825 stride = gfc_conv_array_stride (desc, n);
6827 /* Work out the offset. */
6828 if (info->ref
6829 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6831 gcc_assert (info->subscript[n]
6832 && info->subscript[n]->info->type == GFC_SS_SCALAR);
6833 start = info->subscript[n]->info->data.scalar.value;
6835 else
6837 /* Evaluate and remember the start of the section. */
6838 start = info->start[n];
6839 stride = gfc_evaluate_now (stride, &loop.pre);
6842 tmp = gfc_conv_array_lbound (desc, n);
6843 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
6844 start, tmp);
6845 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
6846 tmp, stride);
6847 offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
6848 offset, tmp);
6850 if (info->ref
6851 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6853 /* For elemental dimensions, we only need the offset. */
6854 continue;
6857 /* Vector subscripts need copying and are handled elsewhere. */
6858 if (info->ref)
6859 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
6861 /* look for the corresponding scalarizer dimension: dim. */
6862 for (dim = 0; dim < ndim; dim++)
6863 if (ss->dim[dim] == n)
6864 break;
6866 /* loop exited early: the DIM being looked for has been found. */
6867 gcc_assert (dim < ndim);
6869 /* Set the new lower bound. */
6870 from = loop.from[dim];
6871 to = loop.to[dim];
6873 /* If we have an array section or are assigning make sure that
6874 the lower bound is 1. References to the full
6875 array should otherwise keep the original bounds. */
6876 if ((!info->ref
6877 || info->ref->u.ar.type != AR_FULL)
6878 && !integer_onep (from))
6880 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6881 gfc_array_index_type, gfc_index_one_node,
6882 from);
6883 to = fold_build2_loc (input_location, PLUS_EXPR,
6884 gfc_array_index_type, to, tmp);
6885 from = gfc_index_one_node;
6887 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
6888 gfc_rank_cst[dim], from);
6890 /* Set the new upper bound. */
6891 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
6892 gfc_rank_cst[dim], to);
6894 /* Multiply the stride by the section stride to get the
6895 total stride. */
6896 stride = fold_build2_loc (input_location, MULT_EXPR,
6897 gfc_array_index_type,
6898 stride, info->stride[n]);
6900 if (se->direct_byref
6901 && ((info->ref && info->ref->u.ar.type != AR_FULL)
6902 || (expr->expr_type == EXPR_ARRAY && se->use_offset)))
6904 base = fold_build2_loc (input_location, MINUS_EXPR,
6905 TREE_TYPE (base), base, stride);
6907 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)) || se->use_offset)
6909 tmp = gfc_conv_array_lbound (desc, n);
6910 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6911 TREE_TYPE (base), tmp, loop.from[dim]);
6912 tmp = fold_build2_loc (input_location, MULT_EXPR,
6913 TREE_TYPE (base), tmp,
6914 gfc_conv_array_stride (desc, n));
6915 base = fold_build2_loc (input_location, PLUS_EXPR,
6916 TREE_TYPE (base), tmp, base);
6919 /* Store the new stride. */
6920 gfc_conv_descriptor_stride_set (&loop.pre, parm,
6921 gfc_rank_cst[dim], stride);
6924 for (n = loop.dimen; n < loop.dimen + codim; n++)
6926 from = loop.from[n];
6927 to = loop.to[n];
6928 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
6929 gfc_rank_cst[n], from);
6930 if (n < loop.dimen + codim - 1)
6931 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
6932 gfc_rank_cst[n], to);
6935 if (se->data_not_needed)
6936 gfc_conv_descriptor_data_set (&loop.pre, parm,
6937 gfc_index_zero_node);
6938 else
6939 /* Point the data pointer at the 1st element in the section. */
6940 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
6941 subref_array_target, expr);
6943 if (((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6944 && !se->data_not_needed)
6945 || (se->use_offset && base != NULL_TREE))
6947 /* Set the offset. */
6948 gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
6950 else
6952 /* Only the callee knows what the correct offset it, so just set
6953 it to zero here. */
6954 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
6956 desc = parm;
6959 if (!se->direct_byref || se->byref_noassign)
6961 /* Get a pointer to the new descriptor. */
6962 if (se->want_pointer)
6963 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6964 else
6965 se->expr = desc;
6968 gfc_add_block_to_block (&se->pre, &loop.pre);
6969 gfc_add_block_to_block (&se->post, &loop.post);
6971 /* Cleanup the scalarizer. */
6972 gfc_cleanup_loop (&loop);
6975 /* Helper function for gfc_conv_array_parameter if array size needs to be
6976 computed. */
6978 static void
6979 array_parameter_size (tree desc, gfc_expr *expr, tree *size)
6981 tree elem;
6982 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6983 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
6984 else if (expr->rank > 1)
6985 *size = build_call_expr_loc (input_location,
6986 gfor_fndecl_size0, 1,
6987 gfc_build_addr_expr (NULL, desc));
6988 else
6990 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
6991 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
6993 *size = fold_build2_loc (input_location, MINUS_EXPR,
6994 gfc_array_index_type, ubound, lbound);
6995 *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6996 *size, gfc_index_one_node);
6997 *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
6998 *size, gfc_index_zero_node);
7000 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
7001 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7002 *size, fold_convert (gfc_array_index_type, elem));
7005 /* Convert an array for passing as an actual parameter. */
7006 /* TODO: Optimize passing g77 arrays. */
7008 void
7009 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
7010 const gfc_symbol *fsym, const char *proc_name,
7011 tree *size)
7013 tree ptr;
7014 tree desc;
7015 tree tmp = NULL_TREE;
7016 tree stmt;
7017 tree parent = DECL_CONTEXT (current_function_decl);
7018 bool full_array_var;
7019 bool this_array_result;
7020 bool contiguous;
7021 bool no_pack;
7022 bool array_constructor;
7023 bool good_allocatable;
7024 bool ultimate_ptr_comp;
7025 bool ultimate_alloc_comp;
7026 gfc_symbol *sym;
7027 stmtblock_t block;
7028 gfc_ref *ref;
7030 ultimate_ptr_comp = false;
7031 ultimate_alloc_comp = false;
7033 for (ref = expr->ref; ref; ref = ref->next)
7035 if (ref->next == NULL)
7036 break;
7038 if (ref->type == REF_COMPONENT)
7040 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
7041 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
7045 full_array_var = false;
7046 contiguous = false;
7048 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
7049 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
7051 sym = full_array_var ? expr->symtree->n.sym : NULL;
7053 /* The symbol should have an array specification. */
7054 gcc_assert (!sym || sym->as || ref->u.ar.as);
7056 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
7058 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
7059 expr->ts.u.cl->backend_decl = tmp;
7060 se->string_length = tmp;
7063 /* Is this the result of the enclosing procedure? */
7064 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
7065 if (this_array_result
7066 && (sym->backend_decl != current_function_decl)
7067 && (sym->backend_decl != parent))
7068 this_array_result = false;
7070 /* Passing address of the array if it is not pointer or assumed-shape. */
7071 if (full_array_var && g77 && !this_array_result
7072 && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
7074 tmp = gfc_get_symbol_decl (sym);
7076 if (sym->ts.type == BT_CHARACTER)
7077 se->string_length = sym->ts.u.cl->backend_decl;
7079 if (!sym->attr.pointer
7080 && sym->as
7081 && sym->as->type != AS_ASSUMED_SHAPE
7082 && sym->as->type != AS_DEFERRED
7083 && sym->as->type != AS_ASSUMED_RANK
7084 && !sym->attr.allocatable)
7086 /* Some variables are declared directly, others are declared as
7087 pointers and allocated on the heap. */
7088 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
7089 se->expr = tmp;
7090 else
7091 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
7092 if (size)
7093 array_parameter_size (tmp, expr, size);
7094 return;
7097 if (sym->attr.allocatable)
7099 if (sym->attr.dummy || sym->attr.result)
7101 gfc_conv_expr_descriptor (se, expr);
7102 tmp = se->expr;
7104 if (size)
7105 array_parameter_size (tmp, expr, size);
7106 se->expr = gfc_conv_array_data (tmp);
7107 return;
7111 /* A convenient reduction in scope. */
7112 contiguous = g77 && !this_array_result && contiguous;
7114 /* There is no need to pack and unpack the array, if it is contiguous
7115 and not a deferred- or assumed-shape array, or if it is simply
7116 contiguous. */
7117 no_pack = ((sym && sym->as
7118 && !sym->attr.pointer
7119 && sym->as->type != AS_DEFERRED
7120 && sym->as->type != AS_ASSUMED_RANK
7121 && sym->as->type != AS_ASSUMED_SHAPE)
7123 (ref && ref->u.ar.as
7124 && ref->u.ar.as->type != AS_DEFERRED
7125 && ref->u.ar.as->type != AS_ASSUMED_RANK
7126 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
7128 gfc_is_simply_contiguous (expr, false));
7130 no_pack = contiguous && no_pack;
7132 /* Array constructors are always contiguous and do not need packing. */
7133 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
7135 /* Same is true of contiguous sections from allocatable variables. */
7136 good_allocatable = contiguous
7137 && expr->symtree
7138 && expr->symtree->n.sym->attr.allocatable;
7140 /* Or ultimate allocatable components. */
7141 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
7143 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
7145 gfc_conv_expr_descriptor (se, expr);
7146 if (expr->ts.type == BT_CHARACTER)
7147 se->string_length = expr->ts.u.cl->backend_decl;
7148 if (size)
7149 array_parameter_size (se->expr, expr, size);
7150 se->expr = gfc_conv_array_data (se->expr);
7151 return;
7154 if (this_array_result)
7156 /* Result of the enclosing function. */
7157 gfc_conv_expr_descriptor (se, expr);
7158 if (size)
7159 array_parameter_size (se->expr, expr, size);
7160 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7162 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
7163 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
7164 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
7165 se->expr));
7167 return;
7169 else
7171 /* Every other type of array. */
7172 se->want_pointer = 1;
7173 gfc_conv_expr_descriptor (se, expr);
7174 if (size)
7175 array_parameter_size (build_fold_indirect_ref_loc (input_location,
7176 se->expr),
7177 expr, size);
7180 /* Deallocate the allocatable components of structures that are
7181 not variable. */
7182 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
7183 && expr->ts.u.derived->attr.alloc_comp
7184 && expr->expr_type != EXPR_VARIABLE)
7186 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
7187 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
7189 /* The components shall be deallocated before their containing entity. */
7190 gfc_prepend_expr_to_block (&se->post, tmp);
7193 if (g77 || (fsym && fsym->attr.contiguous
7194 && !gfc_is_simply_contiguous (expr, false)))
7196 tree origptr = NULL_TREE;
7198 desc = se->expr;
7200 /* For contiguous arrays, save the original value of the descriptor. */
7201 if (!g77)
7203 origptr = gfc_create_var (pvoid_type_node, "origptr");
7204 tmp = build_fold_indirect_ref_loc (input_location, desc);
7205 tmp = gfc_conv_array_data (tmp);
7206 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7207 TREE_TYPE (origptr), origptr,
7208 fold_convert (TREE_TYPE (origptr), tmp));
7209 gfc_add_expr_to_block (&se->pre, tmp);
7212 /* Repack the array. */
7213 if (warn_array_temporaries)
7215 if (fsym)
7216 gfc_warning (OPT_Warray_temporaries,
7217 "Creating array temporary at %L for argument %qs",
7218 &expr->where, fsym->name);
7219 else
7220 gfc_warning (OPT_Warray_temporaries,
7221 "Creating array temporary at %L", &expr->where);
7224 ptr = build_call_expr_loc (input_location,
7225 gfor_fndecl_in_pack, 1, desc);
7227 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7229 tmp = gfc_conv_expr_present (sym);
7230 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
7231 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
7232 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
7235 ptr = gfc_evaluate_now (ptr, &se->pre);
7237 /* Use the packed data for the actual argument, except for contiguous arrays,
7238 where the descriptor's data component is set. */
7239 if (g77)
7240 se->expr = ptr;
7241 else
7243 tmp = build_fold_indirect_ref_loc (input_location, desc);
7245 gfc_ss * ss = gfc_walk_expr (expr);
7246 if (!transposed_dims (ss))
7247 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
7248 else
7250 tree old_field, new_field;
7252 /* The original descriptor has transposed dims so we can't reuse
7253 it directly; we have to create a new one. */
7254 tree old_desc = tmp;
7255 tree new_desc = gfc_create_var (TREE_TYPE (old_desc), "arg_desc");
7257 old_field = gfc_conv_descriptor_dtype (old_desc);
7258 new_field = gfc_conv_descriptor_dtype (new_desc);
7259 gfc_add_modify (&se->pre, new_field, old_field);
7261 old_field = gfc_conv_descriptor_offset (old_desc);
7262 new_field = gfc_conv_descriptor_offset (new_desc);
7263 gfc_add_modify (&se->pre, new_field, old_field);
7265 for (int i = 0; i < expr->rank; i++)
7267 old_field = gfc_conv_descriptor_dimension (old_desc,
7268 gfc_rank_cst[get_array_ref_dim_for_loop_dim (ss, i)]);
7269 new_field = gfc_conv_descriptor_dimension (new_desc,
7270 gfc_rank_cst[i]);
7271 gfc_add_modify (&se->pre, new_field, old_field);
7274 if (flag_coarray == GFC_FCOARRAY_LIB
7275 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (old_desc))
7276 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (old_desc))
7277 == GFC_ARRAY_ALLOCATABLE)
7279 old_field = gfc_conv_descriptor_token (old_desc);
7280 new_field = gfc_conv_descriptor_token (new_desc);
7281 gfc_add_modify (&se->pre, new_field, old_field);
7284 gfc_conv_descriptor_data_set (&se->pre, new_desc, ptr);
7285 se->expr = gfc_build_addr_expr (NULL_TREE, new_desc);
7287 gfc_free_ss (ss);
7290 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
7292 char * msg;
7294 if (fsym && proc_name)
7295 msg = xasprintf ("An array temporary was created for argument "
7296 "'%s' of procedure '%s'", fsym->name, proc_name);
7297 else
7298 msg = xasprintf ("An array temporary was created");
7300 tmp = build_fold_indirect_ref_loc (input_location,
7301 desc);
7302 tmp = gfc_conv_array_data (tmp);
7303 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7304 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7306 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7307 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7308 boolean_type_node,
7309 gfc_conv_expr_present (sym), tmp);
7311 gfc_trans_runtime_check (false, true, tmp, &se->pre,
7312 &expr->where, msg);
7313 free (msg);
7316 gfc_start_block (&block);
7318 /* Copy the data back. */
7319 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
7321 tmp = build_call_expr_loc (input_location,
7322 gfor_fndecl_in_unpack, 2, desc, ptr);
7323 gfc_add_expr_to_block (&block, tmp);
7326 /* Free the temporary. */
7327 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
7328 gfc_add_expr_to_block (&block, tmp);
7330 stmt = gfc_finish_block (&block);
7332 gfc_init_block (&block);
7333 /* Only if it was repacked. This code needs to be executed before the
7334 loop cleanup code. */
7335 tmp = build_fold_indirect_ref_loc (input_location,
7336 desc);
7337 tmp = gfc_conv_array_data (tmp);
7338 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7339 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7341 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7342 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7343 boolean_type_node,
7344 gfc_conv_expr_present (sym), tmp);
7346 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
7348 gfc_add_expr_to_block (&block, tmp);
7349 gfc_add_block_to_block (&block, &se->post);
7351 gfc_init_block (&se->post);
7353 /* Reset the descriptor pointer. */
7354 if (!g77)
7356 tmp = build_fold_indirect_ref_loc (input_location, desc);
7357 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
7360 gfc_add_block_to_block (&se->post, &block);
7365 /* Generate code to deallocate an array, if it is allocated. */
7367 tree
7368 gfc_trans_dealloc_allocated (tree descriptor, bool coarray, gfc_expr *expr)
7370 tree tmp;
7371 tree var;
7372 stmtblock_t block;
7374 gfc_start_block (&block);
7376 var = gfc_conv_descriptor_data_get (descriptor);
7377 STRIP_NOPS (var);
7379 /* Call array_deallocate with an int * present in the second argument.
7380 Although it is ignored here, it's presence ensures that arrays that
7381 are already deallocated are ignored. */
7382 tmp = gfc_deallocate_with_status (coarray ? descriptor : var, NULL_TREE,
7383 NULL_TREE, NULL_TREE, NULL_TREE, true,
7384 expr, coarray);
7385 gfc_add_expr_to_block (&block, tmp);
7387 /* Zero the data pointer. */
7388 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7389 var, build_int_cst (TREE_TYPE (var), 0));
7390 gfc_add_expr_to_block (&block, tmp);
7392 return gfc_finish_block (&block);
7396 /* This helper function calculates the size in words of a full array. */
7398 tree
7399 gfc_full_array_size (stmtblock_t *block, tree decl, int rank)
7401 tree idx;
7402 tree nelems;
7403 tree tmp;
7404 idx = gfc_rank_cst[rank - 1];
7405 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
7406 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
7407 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7408 nelems, tmp);
7409 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7410 tmp, gfc_index_one_node);
7411 tmp = gfc_evaluate_now (tmp, block);
7413 nelems = gfc_conv_descriptor_stride_get (decl, idx);
7414 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7415 nelems, tmp);
7416 return gfc_evaluate_now (tmp, block);
7420 /* Allocate dest to the same size as src, and copy src -> dest.
7421 If no_malloc is set, only the copy is done. */
7423 static tree
7424 duplicate_allocatable (tree dest, tree src, tree type, int rank,
7425 bool no_malloc, bool no_memcpy, tree str_sz)
7427 tree tmp;
7428 tree size;
7429 tree nelems;
7430 tree null_cond;
7431 tree null_data;
7432 stmtblock_t block;
7434 /* If the source is null, set the destination to null. Then,
7435 allocate memory to the destination. */
7436 gfc_init_block (&block);
7438 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
7440 tmp = null_pointer_node;
7441 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type, dest, tmp);
7442 gfc_add_expr_to_block (&block, tmp);
7443 null_data = gfc_finish_block (&block);
7445 gfc_init_block (&block);
7446 if (str_sz != NULL_TREE)
7447 size = str_sz;
7448 else
7449 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
7451 if (!no_malloc)
7453 tmp = gfc_call_malloc (&block, type, size);
7454 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7455 dest, fold_convert (type, tmp));
7456 gfc_add_expr_to_block (&block, tmp);
7459 if (!no_memcpy)
7461 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
7462 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
7463 fold_convert (size_type_node, size));
7464 gfc_add_expr_to_block (&block, tmp);
7467 else
7469 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
7470 null_data = gfc_finish_block (&block);
7472 gfc_init_block (&block);
7473 if (rank)
7474 nelems = gfc_full_array_size (&block, src, rank);
7475 else
7476 nelems = gfc_index_one_node;
7478 if (str_sz != NULL_TREE)
7479 tmp = fold_convert (gfc_array_index_type, str_sz);
7480 else
7481 tmp = fold_convert (gfc_array_index_type,
7482 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
7483 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7484 nelems, tmp);
7485 if (!no_malloc)
7487 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
7488 tmp = gfc_call_malloc (&block, tmp, size);
7489 gfc_conv_descriptor_data_set (&block, dest, tmp);
7492 /* We know the temporary and the value will be the same length,
7493 so can use memcpy. */
7494 if (!no_memcpy)
7496 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
7497 tmp = build_call_expr_loc (input_location, tmp, 3,
7498 gfc_conv_descriptor_data_get (dest),
7499 gfc_conv_descriptor_data_get (src),
7500 fold_convert (size_type_node, size));
7501 gfc_add_expr_to_block (&block, tmp);
7505 tmp = gfc_finish_block (&block);
7507 /* Null the destination if the source is null; otherwise do
7508 the allocate and copy. */
7509 if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (src)))
7510 null_cond = src;
7511 else
7512 null_cond = gfc_conv_descriptor_data_get (src);
7514 null_cond = convert (pvoid_type_node, null_cond);
7515 null_cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7516 null_cond, null_pointer_node);
7517 return build3_v (COND_EXPR, null_cond, tmp, null_data);
7521 /* Allocate dest to the same size as src, and copy data src -> dest. */
7523 tree
7524 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank)
7526 return duplicate_allocatable (dest, src, type, rank, false, false,
7527 NULL_TREE);
7531 /* Copy data src -> dest. */
7533 tree
7534 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
7536 return duplicate_allocatable (dest, src, type, rank, true, false,
7537 NULL_TREE);
7540 /* Allocate dest to the same size as src, but don't copy anything. */
7542 tree
7543 gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank)
7545 return duplicate_allocatable (dest, src, type, rank, false, true, NULL_TREE);
7549 /* Recursively traverse an object of derived type, generating code to
7550 deallocate, nullify or copy allocatable components. This is the work horse
7551 function for the functions named in this enum. */
7553 enum {DEALLOCATE_ALLOC_COMP = 1, DEALLOCATE_ALLOC_COMP_NO_CAF,
7554 NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP, COPY_ONLY_ALLOC_COMP,
7555 COPY_ALLOC_COMP_CAF};
7557 static tree
7558 structure_alloc_comps (gfc_symbol * der_type, tree decl,
7559 tree dest, int rank, int purpose)
7561 gfc_component *c;
7562 gfc_loopinfo loop;
7563 stmtblock_t fnblock;
7564 stmtblock_t loopbody;
7565 stmtblock_t tmpblock;
7566 tree decl_type;
7567 tree tmp;
7568 tree comp;
7569 tree dcmp;
7570 tree nelems;
7571 tree index;
7572 tree var;
7573 tree cdecl;
7574 tree ctype;
7575 tree vref, dref;
7576 tree null_cond = NULL_TREE;
7577 bool called_dealloc_with_status;
7579 gfc_init_block (&fnblock);
7581 decl_type = TREE_TYPE (decl);
7583 if ((POINTER_TYPE_P (decl_type) && rank != 0)
7584 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
7585 decl = build_fold_indirect_ref_loc (input_location, decl);
7587 /* Just in case in gets dereferenced. */
7588 decl_type = TREE_TYPE (decl);
7590 /* If this an array of derived types with allocatable components
7591 build a loop and recursively call this function. */
7592 if (TREE_CODE (decl_type) == ARRAY_TYPE
7593 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
7595 tmp = gfc_conv_array_data (decl);
7596 var = build_fold_indirect_ref_loc (input_location,
7597 tmp);
7599 /* Get the number of elements - 1 and set the counter. */
7600 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
7602 /* Use the descriptor for an allocatable array. Since this
7603 is a full array reference, we only need the descriptor
7604 information from dimension = rank. */
7605 tmp = gfc_full_array_size (&fnblock, decl, rank);
7606 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7607 gfc_array_index_type, tmp,
7608 gfc_index_one_node);
7610 null_cond = gfc_conv_descriptor_data_get (decl);
7611 null_cond = fold_build2_loc (input_location, NE_EXPR,
7612 boolean_type_node, null_cond,
7613 build_int_cst (TREE_TYPE (null_cond), 0));
7615 else
7617 /* Otherwise use the TYPE_DOMAIN information. */
7618 tmp = array_type_nelts (decl_type);
7619 tmp = fold_convert (gfc_array_index_type, tmp);
7622 /* Remember that this is, in fact, the no. of elements - 1. */
7623 nelems = gfc_evaluate_now (tmp, &fnblock);
7624 index = gfc_create_var (gfc_array_index_type, "S");
7626 /* Build the body of the loop. */
7627 gfc_init_block (&loopbody);
7629 vref = gfc_build_array_ref (var, index, NULL);
7631 if (purpose == COPY_ALLOC_COMP)
7633 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
7635 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank);
7636 gfc_add_expr_to_block (&fnblock, tmp);
7638 tmp = build_fold_indirect_ref_loc (input_location,
7639 gfc_conv_array_data (dest));
7640 dref = gfc_build_array_ref (tmp, index, NULL);
7641 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
7643 else if (purpose == COPY_ONLY_ALLOC_COMP)
7645 tmp = build_fold_indirect_ref_loc (input_location,
7646 gfc_conv_array_data (dest));
7647 dref = gfc_build_array_ref (tmp, index, NULL);
7648 tmp = structure_alloc_comps (der_type, vref, dref, rank,
7649 COPY_ALLOC_COMP);
7651 else
7652 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
7654 gfc_add_expr_to_block (&loopbody, tmp);
7656 /* Build the loop and return. */
7657 gfc_init_loopinfo (&loop);
7658 loop.dimen = 1;
7659 loop.from[0] = gfc_index_zero_node;
7660 loop.loopvar[0] = index;
7661 loop.to[0] = nelems;
7662 gfc_trans_scalarizing_loops (&loop, &loopbody);
7663 gfc_add_block_to_block (&fnblock, &loop.pre);
7665 tmp = gfc_finish_block (&fnblock);
7666 if (null_cond != NULL_TREE)
7667 tmp = build3_v (COND_EXPR, null_cond, tmp,
7668 build_empty_stmt (input_location));
7670 return tmp;
7673 /* Otherwise, act on the components or recursively call self to
7674 act on a chain of components. */
7675 for (c = der_type->components; c; c = c->next)
7677 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
7678 || c->ts.type == BT_CLASS)
7679 && c->ts.u.derived->attr.alloc_comp;
7680 cdecl = c->backend_decl;
7681 ctype = TREE_TYPE (cdecl);
7683 switch (purpose)
7685 case DEALLOCATE_ALLOC_COMP:
7686 case DEALLOCATE_ALLOC_COMP_NO_CAF:
7688 /* gfc_deallocate_scalar_with_status calls gfc_deallocate_alloc_comp
7689 (i.e. this function) so generate all the calls and suppress the
7690 recursion from here, if necessary. */
7691 called_dealloc_with_status = false;
7692 gfc_init_block (&tmpblock);
7694 if ((c->ts.type == BT_DERIVED && !c->attr.pointer)
7695 || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer))
7697 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7698 decl, cdecl, NULL_TREE);
7700 /* The finalizer frees allocatable components. */
7701 called_dealloc_with_status
7702 = gfc_add_comp_finalizer_call (&tmpblock, comp, c,
7703 purpose == DEALLOCATE_ALLOC_COMP);
7705 else
7706 comp = NULL_TREE;
7708 if (c->attr.allocatable && !c->attr.proc_pointer
7709 && (c->attr.dimension
7710 || (c->attr.codimension
7711 && purpose != DEALLOCATE_ALLOC_COMP_NO_CAF)))
7713 if (comp == NULL_TREE)
7714 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7715 decl, cdecl, NULL_TREE);
7716 tmp = gfc_trans_dealloc_allocated (comp, c->attr.codimension, NULL);
7717 gfc_add_expr_to_block (&tmpblock, tmp);
7719 else if (c->attr.allocatable && !c->attr.codimension)
7721 /* Allocatable scalar components. */
7722 if (comp == NULL_TREE)
7723 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7724 decl, cdecl, NULL_TREE);
7726 tmp = gfc_deallocate_scalar_with_status (comp, NULL, true, NULL,
7727 c->ts);
7728 gfc_add_expr_to_block (&tmpblock, tmp);
7729 called_dealloc_with_status = true;
7731 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7732 void_type_node, comp,
7733 build_int_cst (TREE_TYPE (comp), 0));
7734 gfc_add_expr_to_block (&tmpblock, tmp);
7736 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable
7737 && (!CLASS_DATA (c)->attr.codimension
7738 || purpose != DEALLOCATE_ALLOC_COMP_NO_CAF))
7740 /* Allocatable CLASS components. */
7742 /* Add reference to '_data' component. */
7743 tmp = CLASS_DATA (c)->backend_decl;
7744 comp = fold_build3_loc (input_location, COMPONENT_REF,
7745 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
7747 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
7748 tmp = gfc_trans_dealloc_allocated (comp,
7749 CLASS_DATA (c)->attr.codimension, NULL);
7750 else
7752 tmp = gfc_deallocate_scalar_with_status (comp, NULL_TREE, true, NULL,
7753 CLASS_DATA (c)->ts);
7754 gfc_add_expr_to_block (&tmpblock, tmp);
7755 called_dealloc_with_status = true;
7757 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7758 void_type_node, comp,
7759 build_int_cst (TREE_TYPE (comp), 0));
7761 gfc_add_expr_to_block (&tmpblock, tmp);
7764 if (cmp_has_alloc_comps
7765 && !c->attr.pointer
7766 && !called_dealloc_with_status)
7768 /* Do not deallocate the components of ultimate pointer
7769 components or iteratively call self if call has been made
7770 to gfc_trans_dealloc_allocated */
7771 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7772 decl, cdecl, NULL_TREE);
7773 rank = c->as ? c->as->rank : 0;
7774 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
7775 rank, purpose);
7776 gfc_add_expr_to_block (&fnblock, tmp);
7779 /* Now add the deallocation of this component. */
7780 gfc_add_block_to_block (&fnblock, &tmpblock);
7781 break;
7783 case NULLIFY_ALLOC_COMP:
7784 if (c->attr.pointer || c->attr.proc_pointer)
7785 continue;
7786 else if (c->attr.allocatable
7787 && (c->attr.dimension|| c->attr.codimension))
7789 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7790 decl, cdecl, NULL_TREE);
7791 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
7793 else if (c->attr.allocatable)
7795 /* Allocatable scalar components. */
7796 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7797 decl, cdecl, NULL_TREE);
7798 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7799 void_type_node, comp,
7800 build_int_cst (TREE_TYPE (comp), 0));
7801 gfc_add_expr_to_block (&fnblock, tmp);
7802 if (gfc_deferred_strlen (c, &comp))
7804 comp = fold_build3_loc (input_location, COMPONENT_REF,
7805 TREE_TYPE (comp),
7806 decl, comp, NULL_TREE);
7807 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7808 TREE_TYPE (comp), comp,
7809 build_int_cst (TREE_TYPE (comp), 0));
7810 gfc_add_expr_to_block (&fnblock, tmp);
7813 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7815 /* Allocatable CLASS components. */
7816 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7817 decl, cdecl, NULL_TREE);
7818 /* Add reference to '_data' component. */
7819 tmp = CLASS_DATA (c)->backend_decl;
7820 comp = fold_build3_loc (input_location, COMPONENT_REF,
7821 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
7822 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (comp)))
7823 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
7824 else
7826 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7827 void_type_node, comp,
7828 build_int_cst (TREE_TYPE (comp), 0));
7829 gfc_add_expr_to_block (&fnblock, tmp);
7832 else if (cmp_has_alloc_comps)
7834 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7835 decl, cdecl, NULL_TREE);
7836 rank = c->as ? c->as->rank : 0;
7837 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
7838 rank, purpose);
7839 gfc_add_expr_to_block (&fnblock, tmp);
7841 break;
7843 case COPY_ALLOC_COMP_CAF:
7844 if (!c->attr.codimension
7845 && (c->ts.type != BT_CLASS || CLASS_DATA (c)->attr.coarray_comp)
7846 && (c->ts.type != BT_DERIVED
7847 || !c->ts.u.derived->attr.coarray_comp))
7848 continue;
7850 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
7851 cdecl, NULL_TREE);
7852 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
7853 cdecl, NULL_TREE);
7855 if (c->attr.codimension)
7857 if (c->ts.type == BT_CLASS)
7859 comp = gfc_class_data_get (comp);
7860 dcmp = gfc_class_data_get (dcmp);
7862 gfc_conv_descriptor_data_set (&fnblock, dcmp,
7863 gfc_conv_descriptor_data_get (comp));
7865 else
7867 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
7868 rank, purpose);
7869 gfc_add_expr_to_block (&fnblock, tmp);
7872 break;
7874 case COPY_ALLOC_COMP:
7875 if (c->attr.pointer)
7876 continue;
7878 /* We need source and destination components. */
7879 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
7880 cdecl, NULL_TREE);
7881 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
7882 cdecl, NULL_TREE);
7883 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
7885 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7887 tree ftn_tree;
7888 tree size;
7889 tree dst_data;
7890 tree src_data;
7891 tree null_data;
7893 dst_data = gfc_class_data_get (dcmp);
7894 src_data = gfc_class_data_get (comp);
7895 size = fold_convert (size_type_node, gfc_vtable_size_get (comp));
7897 if (CLASS_DATA (c)->attr.dimension)
7899 nelems = gfc_conv_descriptor_size (src_data,
7900 CLASS_DATA (c)->as->rank);
7901 size = fold_build2_loc (input_location, MULT_EXPR,
7902 size_type_node, size,
7903 fold_convert (size_type_node,
7904 nelems));
7906 else
7907 nelems = build_int_cst (size_type_node, 1);
7909 if (CLASS_DATA (c)->attr.dimension
7910 || CLASS_DATA (c)->attr.codimension)
7912 src_data = gfc_conv_descriptor_data_get (src_data);
7913 dst_data = gfc_conv_descriptor_data_get (dst_data);
7916 gfc_init_block (&tmpblock);
7918 /* Coarray component have to have the same allocation status and
7919 shape/type-parameter/effective-type on the LHS and RHS of an
7920 intrinsic assignment. Hence, we did not deallocated them - and
7921 do not allocate them here. */
7922 if (!CLASS_DATA (c)->attr.codimension)
7924 ftn_tree = builtin_decl_explicit (BUILT_IN_MALLOC);
7925 tmp = build_call_expr_loc (input_location, ftn_tree, 1, size);
7926 gfc_add_modify (&tmpblock, dst_data,
7927 fold_convert (TREE_TYPE (dst_data), tmp));
7930 tmp = gfc_copy_class_to_class (comp, dcmp, nelems);
7931 gfc_add_expr_to_block (&tmpblock, tmp);
7932 tmp = gfc_finish_block (&tmpblock);
7934 gfc_init_block (&tmpblock);
7935 gfc_add_modify (&tmpblock, dst_data,
7936 fold_convert (TREE_TYPE (dst_data),
7937 null_pointer_node));
7938 null_data = gfc_finish_block (&tmpblock);
7940 null_cond = fold_build2_loc (input_location, NE_EXPR,
7941 boolean_type_node, src_data,
7942 null_pointer_node);
7944 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
7945 tmp, null_data));
7946 continue;
7949 if (gfc_deferred_strlen (c, &tmp))
7951 tree len, size;
7952 len = tmp;
7953 tmp = fold_build3_loc (input_location, COMPONENT_REF,
7954 TREE_TYPE (len),
7955 decl, len, NULL_TREE);
7956 len = fold_build3_loc (input_location, COMPONENT_REF,
7957 TREE_TYPE (len),
7958 dest, len, NULL_TREE);
7959 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7960 TREE_TYPE (len), len, tmp);
7961 gfc_add_expr_to_block (&fnblock, tmp);
7962 size = size_of_string_in_bytes (c->ts.kind, len);
7963 tmp = duplicate_allocatable (dcmp, comp, ctype, rank,
7964 false, false, size);
7965 gfc_add_expr_to_block (&fnblock, tmp);
7967 else if (c->attr.allocatable && !c->attr.proc_pointer
7968 && !cmp_has_alloc_comps)
7970 rank = c->as ? c->as->rank : 0;
7971 if (c->attr.codimension)
7972 tmp = gfc_copy_allocatable_data (dcmp, comp, ctype, rank);
7973 else
7974 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank);
7975 gfc_add_expr_to_block (&fnblock, tmp);
7978 if (cmp_has_alloc_comps)
7980 rank = c->as ? c->as->rank : 0;
7981 tmp = fold_convert (TREE_TYPE (dcmp), comp);
7982 gfc_add_modify (&fnblock, dcmp, tmp);
7983 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
7984 rank, purpose);
7985 gfc_add_expr_to_block (&fnblock, tmp);
7987 break;
7989 default:
7990 gcc_unreachable ();
7991 break;
7995 return gfc_finish_block (&fnblock);
7998 /* Recursively traverse an object of derived type, generating code to
7999 nullify allocatable components. */
8001 tree
8002 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
8004 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
8005 NULLIFY_ALLOC_COMP);
8009 /* Recursively traverse an object of derived type, generating code to
8010 deallocate allocatable components. */
8012 tree
8013 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
8015 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
8016 DEALLOCATE_ALLOC_COMP);
8020 /* Recursively traverse an object of derived type, generating code to
8021 deallocate allocatable components. But do not deallocate coarrays.
8022 To be used for intrinsic assignment, which may not change the allocation
8023 status of coarrays. */
8025 tree
8026 gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank)
8028 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
8029 DEALLOCATE_ALLOC_COMP_NO_CAF);
8033 tree
8034 gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest)
8036 return structure_alloc_comps (der_type, decl, dest, 0, COPY_ALLOC_COMP_CAF);
8040 /* Recursively traverse an object of derived type, generating code to
8041 copy it and its allocatable components. */
8043 tree
8044 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
8046 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
8050 /* Recursively traverse an object of derived type, generating code to
8051 copy only its allocatable components. */
8053 tree
8054 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
8056 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ONLY_ALLOC_COMP);
8060 /* Returns the value of LBOUND for an expression. This could be broken out
8061 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
8062 called by gfc_alloc_allocatable_for_assignment. */
8063 static tree
8064 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
8066 tree lbound;
8067 tree ubound;
8068 tree stride;
8069 tree cond, cond1, cond3, cond4;
8070 tree tmp;
8071 gfc_ref *ref;
8073 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
8075 tmp = gfc_rank_cst[dim];
8076 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
8077 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
8078 stride = gfc_conv_descriptor_stride_get (desc, tmp);
8079 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
8080 ubound, lbound);
8081 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
8082 stride, gfc_index_zero_node);
8083 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
8084 boolean_type_node, cond3, cond1);
8085 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
8086 stride, gfc_index_zero_node);
8087 if (assumed_size)
8088 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8089 tmp, build_int_cst (gfc_array_index_type,
8090 expr->rank - 1));
8091 else
8092 cond = boolean_false_node;
8094 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8095 boolean_type_node, cond3, cond4);
8096 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
8097 boolean_type_node, cond, cond1);
8099 return fold_build3_loc (input_location, COND_EXPR,
8100 gfc_array_index_type, cond,
8101 lbound, gfc_index_one_node);
8104 if (expr->expr_type == EXPR_FUNCTION)
8106 /* A conversion function, so use the argument. */
8107 gcc_assert (expr->value.function.isym
8108 && expr->value.function.isym->conversion);
8109 expr = expr->value.function.actual->expr;
8112 if (expr->expr_type == EXPR_VARIABLE)
8114 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
8115 for (ref = expr->ref; ref; ref = ref->next)
8117 if (ref->type == REF_COMPONENT
8118 && ref->u.c.component->as
8119 && ref->next
8120 && ref->next->u.ar.type == AR_FULL)
8121 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
8123 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
8126 return gfc_index_one_node;
8130 /* Returns true if an expression represents an lhs that can be reallocated
8131 on assignment. */
8133 bool
8134 gfc_is_reallocatable_lhs (gfc_expr *expr)
8136 gfc_ref * ref;
8138 if (!expr->ref)
8139 return false;
8141 /* An allocatable variable. */
8142 if (expr->symtree->n.sym->attr.allocatable
8143 && expr->ref
8144 && expr->ref->type == REF_ARRAY
8145 && expr->ref->u.ar.type == AR_FULL)
8146 return true;
8148 /* All that can be left are allocatable components. */
8149 if ((expr->symtree->n.sym->ts.type != BT_DERIVED
8150 && expr->symtree->n.sym->ts.type != BT_CLASS)
8151 || !expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
8152 return false;
8154 /* Find a component ref followed by an array reference. */
8155 for (ref = expr->ref; ref; ref = ref->next)
8156 if (ref->next
8157 && ref->type == REF_COMPONENT
8158 && ref->next->type == REF_ARRAY
8159 && !ref->next->next)
8160 break;
8162 if (!ref)
8163 return false;
8165 /* Return true if valid reallocatable lhs. */
8166 if (ref->u.c.component->attr.allocatable
8167 && ref->next->u.ar.type == AR_FULL)
8168 return true;
8170 return false;
8174 /* Allocate the lhs of an assignment to an allocatable array, otherwise
8175 reallocate it. */
8177 tree
8178 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
8179 gfc_expr *expr1,
8180 gfc_expr *expr2)
8182 stmtblock_t realloc_block;
8183 stmtblock_t alloc_block;
8184 stmtblock_t fblock;
8185 gfc_ss *rss;
8186 gfc_ss *lss;
8187 gfc_array_info *linfo;
8188 tree realloc_expr;
8189 tree alloc_expr;
8190 tree size1;
8191 tree size2;
8192 tree array1;
8193 tree cond_null;
8194 tree cond;
8195 tree tmp;
8196 tree tmp2;
8197 tree lbound;
8198 tree ubound;
8199 tree desc;
8200 tree old_desc;
8201 tree desc2;
8202 tree offset;
8203 tree jump_label1;
8204 tree jump_label2;
8205 tree neq_size;
8206 tree lbd;
8207 int n;
8208 int dim;
8209 gfc_array_spec * as;
8211 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
8212 Find the lhs expression in the loop chain and set expr1 and
8213 expr2 accordingly. */
8214 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
8216 expr2 = expr1;
8217 /* Find the ss for the lhs. */
8218 lss = loop->ss;
8219 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
8220 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
8221 break;
8222 if (lss == gfc_ss_terminator)
8223 return NULL_TREE;
8224 expr1 = lss->info->expr;
8227 /* Bail out if this is not a valid allocate on assignment. */
8228 if (!gfc_is_reallocatable_lhs (expr1)
8229 || (expr2 && !expr2->rank))
8230 return NULL_TREE;
8232 /* Find the ss for the lhs. */
8233 lss = loop->ss;
8234 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
8235 if (lss->info->expr == expr1)
8236 break;
8238 if (lss == gfc_ss_terminator)
8239 return NULL_TREE;
8241 linfo = &lss->info->data.array;
8243 /* Find an ss for the rhs. For operator expressions, we see the
8244 ss's for the operands. Any one of these will do. */
8245 rss = loop->ss;
8246 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
8247 if (rss->info->expr != expr1 && rss != loop->temp_ss)
8248 break;
8250 if (expr2 && rss == gfc_ss_terminator)
8251 return NULL_TREE;
8253 gfc_start_block (&fblock);
8255 /* Since the lhs is allocatable, this must be a descriptor type.
8256 Get the data and array size. */
8257 desc = linfo->descriptor;
8258 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
8259 array1 = gfc_conv_descriptor_data_get (desc);
8261 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
8262 deallocated if expr is an array of different shape or any of the
8263 corresponding length type parameter values of variable and expr
8264 differ." This assures F95 compatibility. */
8265 jump_label1 = gfc_build_label_decl (NULL_TREE);
8266 jump_label2 = gfc_build_label_decl (NULL_TREE);
8268 /* Allocate if data is NULL. */
8269 cond_null = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8270 array1, build_int_cst (TREE_TYPE (array1), 0));
8271 tmp = build3_v (COND_EXPR, cond_null,
8272 build1_v (GOTO_EXPR, jump_label1),
8273 build_empty_stmt (input_location));
8274 gfc_add_expr_to_block (&fblock, tmp);
8276 /* Get arrayspec if expr is a full array. */
8277 if (expr2 && expr2->expr_type == EXPR_FUNCTION
8278 && expr2->value.function.isym
8279 && expr2->value.function.isym->conversion)
8281 /* For conversion functions, take the arg. */
8282 gfc_expr *arg = expr2->value.function.actual->expr;
8283 as = gfc_get_full_arrayspec_from_expr (arg);
8285 else if (expr2)
8286 as = gfc_get_full_arrayspec_from_expr (expr2);
8287 else
8288 as = NULL;
8290 /* If the lhs shape is not the same as the rhs jump to setting the
8291 bounds and doing the reallocation....... */
8292 for (n = 0; n < expr1->rank; n++)
8294 /* Check the shape. */
8295 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
8296 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
8297 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8298 gfc_array_index_type,
8299 loop->to[n], loop->from[n]);
8300 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8301 gfc_array_index_type,
8302 tmp, lbound);
8303 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8304 gfc_array_index_type,
8305 tmp, ubound);
8306 cond = fold_build2_loc (input_location, NE_EXPR,
8307 boolean_type_node,
8308 tmp, gfc_index_zero_node);
8309 tmp = build3_v (COND_EXPR, cond,
8310 build1_v (GOTO_EXPR, jump_label1),
8311 build_empty_stmt (input_location));
8312 gfc_add_expr_to_block (&fblock, tmp);
8315 /* ....else jump past the (re)alloc code. */
8316 tmp = build1_v (GOTO_EXPR, jump_label2);
8317 gfc_add_expr_to_block (&fblock, tmp);
8319 /* Add the label to start automatic (re)allocation. */
8320 tmp = build1_v (LABEL_EXPR, jump_label1);
8321 gfc_add_expr_to_block (&fblock, tmp);
8323 /* If the lhs has not been allocated, its bounds will not have been
8324 initialized and so its size is set to zero. */
8325 size1 = gfc_create_var (gfc_array_index_type, NULL);
8326 gfc_init_block (&alloc_block);
8327 gfc_add_modify (&alloc_block, size1, gfc_index_zero_node);
8328 gfc_init_block (&realloc_block);
8329 gfc_add_modify (&realloc_block, size1,
8330 gfc_conv_descriptor_size (desc, expr1->rank));
8331 tmp = build3_v (COND_EXPR, cond_null,
8332 gfc_finish_block (&alloc_block),
8333 gfc_finish_block (&realloc_block));
8334 gfc_add_expr_to_block (&fblock, tmp);
8336 /* Get the rhs size and fix it. */
8337 if (expr2)
8338 desc2 = rss->info->data.array.descriptor;
8339 else
8340 desc2 = NULL_TREE;
8342 size2 = gfc_index_one_node;
8343 for (n = 0; n < expr2->rank; n++)
8345 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8346 gfc_array_index_type,
8347 loop->to[n], loop->from[n]);
8348 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8349 gfc_array_index_type,
8350 tmp, gfc_index_one_node);
8351 size2 = fold_build2_loc (input_location, MULT_EXPR,
8352 gfc_array_index_type,
8353 tmp, size2);
8355 size2 = gfc_evaluate_now (size2, &fblock);
8357 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
8358 size1, size2);
8359 neq_size = gfc_evaluate_now (cond, &fblock);
8361 /* Deallocation of allocatable components will have to occur on
8362 reallocation. Fix the old descriptor now. */
8363 if ((expr1->ts.type == BT_DERIVED)
8364 && expr1->ts.u.derived->attr.alloc_comp)
8365 old_desc = gfc_evaluate_now (desc, &fblock);
8366 else
8367 old_desc = NULL_TREE;
8369 /* Now modify the lhs descriptor and the associated scalarizer
8370 variables. F2003 7.4.1.3: "If variable is or becomes an
8371 unallocated allocatable variable, then it is allocated with each
8372 deferred type parameter equal to the corresponding type parameters
8373 of expr , with the shape of expr , and with each lower bound equal
8374 to the corresponding element of LBOUND(expr)."
8375 Reuse size1 to keep a dimension-by-dimension track of the
8376 stride of the new array. */
8377 size1 = gfc_index_one_node;
8378 offset = gfc_index_zero_node;
8380 for (n = 0; n < expr2->rank; n++)
8382 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8383 gfc_array_index_type,
8384 loop->to[n], loop->from[n]);
8385 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8386 gfc_array_index_type,
8387 tmp, gfc_index_one_node);
8389 lbound = gfc_index_one_node;
8390 ubound = tmp;
8392 if (as)
8394 lbd = get_std_lbound (expr2, desc2, n,
8395 as->type == AS_ASSUMED_SIZE);
8396 ubound = fold_build2_loc (input_location,
8397 MINUS_EXPR,
8398 gfc_array_index_type,
8399 ubound, lbound);
8400 ubound = fold_build2_loc (input_location,
8401 PLUS_EXPR,
8402 gfc_array_index_type,
8403 ubound, lbd);
8404 lbound = lbd;
8407 gfc_conv_descriptor_lbound_set (&fblock, desc,
8408 gfc_rank_cst[n],
8409 lbound);
8410 gfc_conv_descriptor_ubound_set (&fblock, desc,
8411 gfc_rank_cst[n],
8412 ubound);
8413 gfc_conv_descriptor_stride_set (&fblock, desc,
8414 gfc_rank_cst[n],
8415 size1);
8416 lbound = gfc_conv_descriptor_lbound_get (desc,
8417 gfc_rank_cst[n]);
8418 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
8419 gfc_array_index_type,
8420 lbound, size1);
8421 offset = fold_build2_loc (input_location, MINUS_EXPR,
8422 gfc_array_index_type,
8423 offset, tmp2);
8424 size1 = fold_build2_loc (input_location, MULT_EXPR,
8425 gfc_array_index_type,
8426 tmp, size1);
8429 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
8430 the array offset is saved and the info.offset is used for a
8431 running offset. Use the saved_offset instead. */
8432 tmp = gfc_conv_descriptor_offset (desc);
8433 gfc_add_modify (&fblock, tmp, offset);
8434 if (linfo->saved_offset
8435 && TREE_CODE (linfo->saved_offset) == VAR_DECL)
8436 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
8438 /* Now set the deltas for the lhs. */
8439 for (n = 0; n < expr1->rank; n++)
8441 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
8442 dim = lss->dim[n];
8443 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8444 gfc_array_index_type, tmp,
8445 loop->from[dim]);
8446 if (linfo->delta[dim]
8447 && TREE_CODE (linfo->delta[dim]) == VAR_DECL)
8448 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
8451 /* Get the new lhs size in bytes. */
8452 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
8454 if (expr2->ts.deferred)
8456 if (TREE_CODE (expr2->ts.u.cl->backend_decl) == VAR_DECL)
8457 tmp = expr2->ts.u.cl->backend_decl;
8458 else
8459 tmp = rss->info->string_length;
8461 else
8463 tmp = expr2->ts.u.cl->backend_decl;
8464 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
8467 if (expr1->ts.u.cl->backend_decl
8468 && TREE_CODE (expr1->ts.u.cl->backend_decl) == VAR_DECL)
8469 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
8470 else
8471 gfc_add_modify (&fblock, lss->info->string_length, tmp);
8473 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
8475 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
8476 tmp = fold_build2_loc (input_location, MULT_EXPR,
8477 gfc_array_index_type, tmp,
8478 expr1->ts.u.cl->backend_decl);
8480 else
8481 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
8482 tmp = fold_convert (gfc_array_index_type, tmp);
8483 size2 = fold_build2_loc (input_location, MULT_EXPR,
8484 gfc_array_index_type,
8485 tmp, size2);
8486 size2 = fold_convert (size_type_node, size2);
8487 size2 = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
8488 size2, size_one_node);
8489 size2 = gfc_evaluate_now (size2, &fblock);
8491 /* Realloc expression. Note that the scalarizer uses desc.data
8492 in the array reference - (*desc.data)[<element>]. */
8493 gfc_init_block (&realloc_block);
8495 if ((expr1->ts.type == BT_DERIVED)
8496 && expr1->ts.u.derived->attr.alloc_comp)
8498 tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc,
8499 expr1->rank);
8500 gfc_add_expr_to_block (&realloc_block, tmp);
8503 tmp = build_call_expr_loc (input_location,
8504 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
8505 fold_convert (pvoid_type_node, array1),
8506 size2);
8507 gfc_conv_descriptor_data_set (&realloc_block,
8508 desc, tmp);
8510 if ((expr1->ts.type == BT_DERIVED)
8511 && expr1->ts.u.derived->attr.alloc_comp)
8513 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
8514 expr1->rank);
8515 gfc_add_expr_to_block (&realloc_block, tmp);
8518 realloc_expr = gfc_finish_block (&realloc_block);
8520 /* Only reallocate if sizes are different. */
8521 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
8522 build_empty_stmt (input_location));
8523 realloc_expr = tmp;
8526 /* Malloc expression. */
8527 gfc_init_block (&alloc_block);
8528 tmp = build_call_expr_loc (input_location,
8529 builtin_decl_explicit (BUILT_IN_MALLOC),
8530 1, size2);
8531 gfc_conv_descriptor_data_set (&alloc_block,
8532 desc, tmp);
8533 tmp = gfc_conv_descriptor_dtype (desc);
8534 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
8535 if ((expr1->ts.type == BT_DERIVED)
8536 && expr1->ts.u.derived->attr.alloc_comp)
8538 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
8539 expr1->rank);
8540 gfc_add_expr_to_block (&alloc_block, tmp);
8542 alloc_expr = gfc_finish_block (&alloc_block);
8544 /* Malloc if not allocated; realloc otherwise. */
8545 tmp = build_int_cst (TREE_TYPE (array1), 0);
8546 cond = fold_build2_loc (input_location, EQ_EXPR,
8547 boolean_type_node,
8548 array1, tmp);
8549 tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
8550 gfc_add_expr_to_block (&fblock, tmp);
8552 /* Make sure that the scalarizer data pointer is updated. */
8553 if (linfo->data
8554 && TREE_CODE (linfo->data) == VAR_DECL)
8556 tmp = gfc_conv_descriptor_data_get (desc);
8557 gfc_add_modify (&fblock, linfo->data, tmp);
8560 /* Add the exit label. */
8561 tmp = build1_v (LABEL_EXPR, jump_label2);
8562 gfc_add_expr_to_block (&fblock, tmp);
8564 return gfc_finish_block (&fblock);
8568 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
8569 Do likewise, recursively if necessary, with the allocatable components of
8570 derived types. */
8572 void
8573 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
8575 tree type;
8576 tree tmp;
8577 tree descriptor;
8578 stmtblock_t init;
8579 stmtblock_t cleanup;
8580 locus loc;
8581 int rank;
8582 bool sym_has_alloc_comp, has_finalizer;
8584 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
8585 || sym->ts.type == BT_CLASS)
8586 && sym->ts.u.derived->attr.alloc_comp;
8587 has_finalizer = sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED
8588 ? gfc_is_finalizable (sym->ts.u.derived, NULL) : false;
8590 /* Make sure the frontend gets these right. */
8591 gcc_assert (sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp
8592 || has_finalizer);
8594 gfc_save_backend_locus (&loc);
8595 gfc_set_backend_locus (&sym->declared_at);
8596 gfc_init_block (&init);
8598 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
8599 || TREE_CODE (sym->backend_decl) == PARM_DECL);
8601 if (sym->ts.type == BT_CHARACTER
8602 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
8604 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
8605 gfc_trans_vla_type_sizes (sym, &init);
8608 /* Dummy, use associated and result variables don't need anything special. */
8609 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
8611 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
8612 gfc_restore_backend_locus (&loc);
8613 return;
8616 descriptor = sym->backend_decl;
8618 /* Although static, derived types with default initializers and
8619 allocatable components must not be nulled wholesale; instead they
8620 are treated component by component. */
8621 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp && !has_finalizer)
8623 /* SAVEd variables are not freed on exit. */
8624 gfc_trans_static_array_pointer (sym);
8626 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
8627 gfc_restore_backend_locus (&loc);
8628 return;
8631 /* Get the descriptor type. */
8632 type = TREE_TYPE (sym->backend_decl);
8634 if ((sym_has_alloc_comp || (has_finalizer && sym->ts.type != BT_CLASS))
8635 && !(sym->attr.pointer || sym->attr.allocatable))
8637 if (!sym->attr.save
8638 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
8640 if (sym->value == NULL
8641 || !gfc_has_default_initializer (sym->ts.u.derived))
8643 rank = sym->as ? sym->as->rank : 0;
8644 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
8645 descriptor, rank);
8646 gfc_add_expr_to_block (&init, tmp);
8648 else
8649 gfc_init_default_dt (sym, &init, false);
8652 else if (!GFC_DESCRIPTOR_TYPE_P (type))
8654 /* If the backend_decl is not a descriptor, we must have a pointer
8655 to one. */
8656 descriptor = build_fold_indirect_ref_loc (input_location,
8657 sym->backend_decl);
8658 type = TREE_TYPE (descriptor);
8661 /* NULLIFY the data pointer, for non-saved allocatables. */
8662 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save && sym->attr.allocatable)
8663 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
8665 gfc_restore_backend_locus (&loc);
8666 gfc_init_block (&cleanup);
8668 /* Allocatable arrays need to be freed when they go out of scope.
8669 The allocatable components of pointers must not be touched. */
8670 if (!sym->attr.allocatable && has_finalizer && sym->ts.type != BT_CLASS
8671 && !sym->attr.pointer && !sym->attr.artificial && !sym->attr.save
8672 && !sym->ns->proc_name->attr.is_main_program)
8674 gfc_expr *e;
8675 sym->attr.referenced = 1;
8676 e = gfc_lval_expr_from_sym (sym);
8677 gfc_add_finalizer_call (&cleanup, e);
8678 gfc_free_expr (e);
8680 else if ((!sym->attr.allocatable || !has_finalizer)
8681 && sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
8682 && !sym->attr.pointer && !sym->attr.save
8683 && !sym->ns->proc_name->attr.is_main_program)
8685 int rank;
8686 rank = sym->as ? sym->as->rank : 0;
8687 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
8688 gfc_add_expr_to_block (&cleanup, tmp);
8691 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
8692 && !sym->attr.save && !sym->attr.result
8693 && !sym->ns->proc_name->attr.is_main_program)
8695 gfc_expr *e;
8696 e = has_finalizer ? gfc_lval_expr_from_sym (sym) : NULL;
8697 tmp = gfc_trans_dealloc_allocated (sym->backend_decl,
8698 sym->attr.codimension, e);
8699 if (e)
8700 gfc_free_expr (e);
8701 gfc_add_expr_to_block (&cleanup, tmp);
8704 gfc_add_init_cleanup (block, gfc_finish_block (&init),
8705 gfc_finish_block (&cleanup));
8708 /************ Expression Walking Functions ******************/
8710 /* Walk a variable reference.
8712 Possible extension - multiple component subscripts.
8713 x(:,:) = foo%a(:)%b(:)
8714 Transforms to
8715 forall (i=..., j=...)
8716 x(i,j) = foo%a(j)%b(i)
8717 end forall
8718 This adds a fair amount of complexity because you need to deal with more
8719 than one ref. Maybe handle in a similar manner to vector subscripts.
8720 Maybe not worth the effort. */
8723 static gfc_ss *
8724 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
8726 gfc_ref *ref;
8728 for (ref = expr->ref; ref; ref = ref->next)
8729 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
8730 break;
8732 return gfc_walk_array_ref (ss, expr, ref);
8736 gfc_ss *
8737 gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
8739 gfc_array_ref *ar;
8740 gfc_ss *newss;
8741 int n;
8743 for (; ref; ref = ref->next)
8745 if (ref->type == REF_SUBSTRING)
8747 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
8748 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
8751 /* We're only interested in array sections from now on. */
8752 if (ref->type != REF_ARRAY)
8753 continue;
8755 ar = &ref->u.ar;
8757 switch (ar->type)
8759 case AR_ELEMENT:
8760 for (n = ar->dimen - 1; n >= 0; n--)
8761 ss = gfc_get_scalar_ss (ss, ar->start[n]);
8762 break;
8764 case AR_FULL:
8765 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
8766 newss->info->data.array.ref = ref;
8768 /* Make sure array is the same as array(:,:), this way
8769 we don't need to special case all the time. */
8770 ar->dimen = ar->as->rank;
8771 for (n = 0; n < ar->dimen; n++)
8773 ar->dimen_type[n] = DIMEN_RANGE;
8775 gcc_assert (ar->start[n] == NULL);
8776 gcc_assert (ar->end[n] == NULL);
8777 gcc_assert (ar->stride[n] == NULL);
8779 ss = newss;
8780 break;
8782 case AR_SECTION:
8783 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
8784 newss->info->data.array.ref = ref;
8786 /* We add SS chains for all the subscripts in the section. */
8787 for (n = 0; n < ar->dimen; n++)
8789 gfc_ss *indexss;
8791 switch (ar->dimen_type[n])
8793 case DIMEN_ELEMENT:
8794 /* Add SS for elemental (scalar) subscripts. */
8795 gcc_assert (ar->start[n]);
8796 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
8797 indexss->loop_chain = gfc_ss_terminator;
8798 newss->info->data.array.subscript[n] = indexss;
8799 break;
8801 case DIMEN_RANGE:
8802 /* We don't add anything for sections, just remember this
8803 dimension for later. */
8804 newss->dim[newss->dimen] = n;
8805 newss->dimen++;
8806 break;
8808 case DIMEN_VECTOR:
8809 /* Create a GFC_SS_VECTOR index in which we can store
8810 the vector's descriptor. */
8811 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
8812 1, GFC_SS_VECTOR);
8813 indexss->loop_chain = gfc_ss_terminator;
8814 newss->info->data.array.subscript[n] = indexss;
8815 newss->dim[newss->dimen] = n;
8816 newss->dimen++;
8817 break;
8819 default:
8820 /* We should know what sort of section it is by now. */
8821 gcc_unreachable ();
8824 /* We should have at least one non-elemental dimension,
8825 unless we are creating a descriptor for a (scalar) coarray. */
8826 gcc_assert (newss->dimen > 0
8827 || newss->info->data.array.ref->u.ar.as->corank > 0);
8828 ss = newss;
8829 break;
8831 default:
8832 /* We should know what sort of section it is by now. */
8833 gcc_unreachable ();
8837 return ss;
8841 /* Walk an expression operator. If only one operand of a binary expression is
8842 scalar, we must also add the scalar term to the SS chain. */
8844 static gfc_ss *
8845 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
8847 gfc_ss *head;
8848 gfc_ss *head2;
8850 head = gfc_walk_subexpr (ss, expr->value.op.op1);
8851 if (expr->value.op.op2 == NULL)
8852 head2 = head;
8853 else
8854 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
8856 /* All operands are scalar. Pass back and let the caller deal with it. */
8857 if (head2 == ss)
8858 return head2;
8860 /* All operands require scalarization. */
8861 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
8862 return head2;
8864 /* One of the operands needs scalarization, the other is scalar.
8865 Create a gfc_ss for the scalar expression. */
8866 if (head == ss)
8868 /* First operand is scalar. We build the chain in reverse order, so
8869 add the scalar SS after the second operand. */
8870 head = head2;
8871 while (head && head->next != ss)
8872 head = head->next;
8873 /* Check we haven't somehow broken the chain. */
8874 gcc_assert (head);
8875 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
8877 else /* head2 == head */
8879 gcc_assert (head2 == head);
8880 /* Second operand is scalar. */
8881 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
8884 return head2;
8888 /* Reverse a SS chain. */
8890 gfc_ss *
8891 gfc_reverse_ss (gfc_ss * ss)
8893 gfc_ss *next;
8894 gfc_ss *head;
8896 gcc_assert (ss != NULL);
8898 head = gfc_ss_terminator;
8899 while (ss != gfc_ss_terminator)
8901 next = ss->next;
8902 /* Check we didn't somehow break the chain. */
8903 gcc_assert (next != NULL);
8904 ss->next = head;
8905 head = ss;
8906 ss = next;
8909 return (head);
8913 /* Given an expression referring to a procedure, return the symbol of its
8914 interface. We can't get the procedure symbol directly as we have to handle
8915 the case of (deferred) type-bound procedures. */
8917 gfc_symbol *
8918 gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
8920 gfc_symbol *sym;
8921 gfc_ref *ref;
8923 if (procedure_ref == NULL)
8924 return NULL;
8926 /* Normal procedure case. */
8927 sym = procedure_ref->symtree->n.sym;
8929 /* Typebound procedure case. */
8930 for (ref = procedure_ref->ref; ref; ref = ref->next)
8932 if (ref->type == REF_COMPONENT
8933 && ref->u.c.component->attr.proc_pointer)
8934 sym = ref->u.c.component->ts.interface;
8935 else
8936 sym = NULL;
8939 return sym;
8943 /* Walk the arguments of an elemental function.
8944 PROC_EXPR is used to check whether an argument is permitted to be absent. If
8945 it is NULL, we don't do the check and the argument is assumed to be present.
8948 gfc_ss *
8949 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
8950 gfc_symbol *proc_ifc, gfc_ss_type type)
8952 gfc_formal_arglist *dummy_arg;
8953 int scalar;
8954 gfc_ss *head;
8955 gfc_ss *tail;
8956 gfc_ss *newss;
8958 head = gfc_ss_terminator;
8959 tail = NULL;
8961 if (proc_ifc)
8962 dummy_arg = gfc_sym_get_dummy_args (proc_ifc);
8963 else
8964 dummy_arg = NULL;
8966 scalar = 1;
8967 for (; arg; arg = arg->next)
8969 if (!arg->expr || arg->expr->expr_type == EXPR_NULL)
8970 continue;
8972 newss = gfc_walk_subexpr (head, arg->expr);
8973 if (newss == head)
8975 /* Scalar argument. */
8976 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
8977 newss = gfc_get_scalar_ss (head, arg->expr);
8978 newss->info->type = type;
8981 else
8982 scalar = 0;
8984 if (dummy_arg != NULL
8985 && dummy_arg->sym->attr.optional
8986 && arg->expr->expr_type == EXPR_VARIABLE
8987 && (gfc_expr_attr (arg->expr).optional
8988 || gfc_expr_attr (arg->expr).allocatable
8989 || gfc_expr_attr (arg->expr).pointer))
8990 newss->info->can_be_null_ref = true;
8992 head = newss;
8993 if (!tail)
8995 tail = head;
8996 while (tail->next != gfc_ss_terminator)
8997 tail = tail->next;
9000 if (dummy_arg != NULL)
9001 dummy_arg = dummy_arg->next;
9004 if (scalar)
9006 /* If all the arguments are scalar we don't need the argument SS. */
9007 gfc_free_ss_chain (head);
9008 /* Pass it back. */
9009 return ss;
9012 /* Add it onto the existing chain. */
9013 tail->next = ss;
9014 return head;
9018 /* Walk a function call. Scalar functions are passed back, and taken out of
9019 scalarization loops. For elemental functions we walk their arguments.
9020 The result of functions returning arrays is stored in a temporary outside
9021 the loop, so that the function is only called once. Hence we do not need
9022 to walk their arguments. */
9024 static gfc_ss *
9025 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
9027 gfc_intrinsic_sym *isym;
9028 gfc_symbol *sym;
9029 gfc_component *comp = NULL;
9031 isym = expr->value.function.isym;
9033 /* Handle intrinsic functions separately. */
9034 if (isym)
9035 return gfc_walk_intrinsic_function (ss, expr, isym);
9037 sym = expr->value.function.esym;
9038 if (!sym)
9039 sym = expr->symtree->n.sym;
9041 /* A function that returns arrays. */
9042 comp = gfc_get_proc_ptr_comp (expr);
9043 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
9044 || (comp && comp->attr.dimension))
9045 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
9047 /* Walk the parameters of an elemental function. For now we always pass
9048 by reference. */
9049 if (sym->attr.elemental || (comp && comp->attr.elemental))
9050 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
9051 gfc_get_proc_ifc_for_expr (expr),
9052 GFC_SS_REFERENCE);
9054 /* Scalar functions are OK as these are evaluated outside the scalarization
9055 loop. Pass back and let the caller deal with it. */
9056 return ss;
9060 /* An array temporary is constructed for array constructors. */
9062 static gfc_ss *
9063 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
9065 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
9069 /* Walk an expression. Add walked expressions to the head of the SS chain.
9070 A wholly scalar expression will not be added. */
9072 gfc_ss *
9073 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
9075 gfc_ss *head;
9077 switch (expr->expr_type)
9079 case EXPR_VARIABLE:
9080 head = gfc_walk_variable_expr (ss, expr);
9081 return head;
9083 case EXPR_OP:
9084 head = gfc_walk_op_expr (ss, expr);
9085 return head;
9087 case EXPR_FUNCTION:
9088 head = gfc_walk_function_expr (ss, expr);
9089 return head;
9091 case EXPR_CONSTANT:
9092 case EXPR_NULL:
9093 case EXPR_STRUCTURE:
9094 /* Pass back and let the caller deal with it. */
9095 break;
9097 case EXPR_ARRAY:
9098 head = gfc_walk_array_constructor (ss, expr);
9099 return head;
9101 case EXPR_SUBSTRING:
9102 /* Pass back and let the caller deal with it. */
9103 break;
9105 default:
9106 gfc_internal_error ("bad expression type during walk (%d)",
9107 expr->expr_type);
9109 return ss;
9113 /* Entry point for expression walking.
9114 A return value equal to the passed chain means this is
9115 a scalar expression. It is up to the caller to take whatever action is
9116 necessary to translate these. */
9118 gfc_ss *
9119 gfc_walk_expr (gfc_expr * expr)
9121 gfc_ss *res;
9123 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
9124 return gfc_reverse_ss (res);