2013-02-21 Janus Weil <janus@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-array.c
blob75fed2f651cd13ed4470e793a9077654a8f9b967
1 /* Array translation routines
2 Copyright (C) 2002-2013 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
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 "tree.h"
82 #include "gimple.h" /* For create_tmp_var_name. */
83 #include "diagnostic-core.h" /* For internal_error/fatal_error. */
84 #include "flags.h"
85 #include "gfortran.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"
94 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
96 /* The contents of this structure aren't actually used, just the address. */
97 static gfc_ss gfc_ss_terminator_var;
98 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
101 static tree
102 gfc_array_dataptr_type (tree desc)
104 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
108 /* Build expressions to access the members of an array descriptor.
109 It's surprisingly easy to mess up here, so never access
110 an array descriptor by "brute force", always use these
111 functions. This also avoids problems if we change the format
112 of an array descriptor.
114 To understand these magic numbers, look at the comments
115 before gfc_build_array_type() in trans-types.c.
117 The code within these defines should be the only code which knows the format
118 of an array descriptor.
120 Any code just needing to read obtain the bounds of an array should use
121 gfc_conv_array_* rather than the following functions as these will return
122 know constant values, and work with arrays which do not have descriptors.
124 Don't forget to #undef these! */
126 #define DATA_FIELD 0
127 #define OFFSET_FIELD 1
128 #define DTYPE_FIELD 2
129 #define DIMENSION_FIELD 3
130 #define CAF_TOKEN_FIELD 4
132 #define STRIDE_SUBFIELD 0
133 #define LBOUND_SUBFIELD 1
134 #define UBOUND_SUBFIELD 2
136 /* This provides READ-ONLY access to the data field. The field itself
137 doesn't have the proper type. */
139 tree
140 gfc_conv_descriptor_data_get (tree desc)
142 tree field, type, t;
144 type = TREE_TYPE (desc);
145 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
147 field = TYPE_FIELDS (type);
148 gcc_assert (DATA_FIELD == 0);
150 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
151 field, NULL_TREE);
152 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
154 return t;
157 /* This provides WRITE access to the data field.
159 TUPLES_P is true if we are generating tuples.
161 This function gets called through the following macros:
162 gfc_conv_descriptor_data_set
163 gfc_conv_descriptor_data_set. */
165 void
166 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
168 tree field, type, t;
170 type = TREE_TYPE (desc);
171 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
173 field = TYPE_FIELDS (type);
174 gcc_assert (DATA_FIELD == 0);
176 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
177 field, NULL_TREE);
178 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
182 /* This provides address access to the data field. This should only be
183 used by array allocation, passing this on to the runtime. */
185 tree
186 gfc_conv_descriptor_data_addr (tree desc)
188 tree field, type, t;
190 type = TREE_TYPE (desc);
191 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
193 field = TYPE_FIELDS (type);
194 gcc_assert (DATA_FIELD == 0);
196 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
197 field, NULL_TREE);
198 return gfc_build_addr_expr (NULL_TREE, t);
201 static tree
202 gfc_conv_descriptor_offset (tree desc)
204 tree type;
205 tree field;
207 type = TREE_TYPE (desc);
208 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
210 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
211 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
213 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
214 desc, field, NULL_TREE);
217 tree
218 gfc_conv_descriptor_offset_get (tree desc)
220 return gfc_conv_descriptor_offset (desc);
223 void
224 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
225 tree value)
227 tree t = gfc_conv_descriptor_offset (desc);
228 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
232 tree
233 gfc_conv_descriptor_dtype (tree desc)
235 tree field;
236 tree type;
238 type = TREE_TYPE (desc);
239 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
241 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
242 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
244 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
245 desc, field, NULL_TREE);
249 tree
250 gfc_conv_descriptor_rank (tree desc)
252 tree tmp;
253 tree dtype;
255 dtype = gfc_conv_descriptor_dtype (desc);
256 tmp = build_int_cst (TREE_TYPE (dtype), GFC_DTYPE_RANK_MASK);
257 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (dtype),
258 dtype, tmp);
259 return fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
263 tree
264 gfc_get_descriptor_dimension (tree desc)
266 tree type, field;
268 type = TREE_TYPE (desc);
269 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
271 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
272 gcc_assert (field != NULL_TREE
273 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
274 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
276 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
277 desc, field, NULL_TREE);
281 static tree
282 gfc_conv_descriptor_dimension (tree desc, tree dim)
284 tree tmp;
286 tmp = gfc_get_descriptor_dimension (desc);
288 return gfc_build_array_ref (tmp, dim, NULL);
292 tree
293 gfc_conv_descriptor_token (tree desc)
295 tree type;
296 tree field;
298 type = TREE_TYPE (desc);
299 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
300 gcc_assert (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE);
301 gcc_assert (gfc_option.coarray == GFC_FCOARRAY_LIB);
302 field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
303 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == prvoid_type_node);
305 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
306 desc, field, NULL_TREE);
310 static tree
311 gfc_conv_descriptor_stride (tree desc, tree dim)
313 tree tmp;
314 tree field;
316 tmp = gfc_conv_descriptor_dimension (desc, dim);
317 field = TYPE_FIELDS (TREE_TYPE (tmp));
318 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
319 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
321 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
322 tmp, field, NULL_TREE);
323 return tmp;
326 tree
327 gfc_conv_descriptor_stride_get (tree desc, tree dim)
329 tree type = TREE_TYPE (desc);
330 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
331 if (integer_zerop (dim)
332 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
333 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
334 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
335 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
336 return gfc_index_one_node;
338 return gfc_conv_descriptor_stride (desc, dim);
341 void
342 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
343 tree dim, tree value)
345 tree t = gfc_conv_descriptor_stride (desc, dim);
346 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
349 static tree
350 gfc_conv_descriptor_lbound (tree desc, tree dim)
352 tree tmp;
353 tree field;
355 tmp = gfc_conv_descriptor_dimension (desc, dim);
356 field = TYPE_FIELDS (TREE_TYPE (tmp));
357 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
358 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
360 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
361 tmp, field, NULL_TREE);
362 return tmp;
365 tree
366 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
368 return gfc_conv_descriptor_lbound (desc, dim);
371 void
372 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
373 tree dim, tree value)
375 tree t = gfc_conv_descriptor_lbound (desc, dim);
376 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
379 static tree
380 gfc_conv_descriptor_ubound (tree desc, tree dim)
382 tree tmp;
383 tree field;
385 tmp = gfc_conv_descriptor_dimension (desc, dim);
386 field = TYPE_FIELDS (TREE_TYPE (tmp));
387 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
388 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
390 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
391 tmp, field, NULL_TREE);
392 return tmp;
395 tree
396 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
398 return gfc_conv_descriptor_ubound (desc, dim);
401 void
402 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
403 tree dim, tree value)
405 tree t = gfc_conv_descriptor_ubound (desc, dim);
406 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
409 /* Build a null array descriptor constructor. */
411 tree
412 gfc_build_null_descriptor (tree type)
414 tree field;
415 tree tmp;
417 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
418 gcc_assert (DATA_FIELD == 0);
419 field = TYPE_FIELDS (type);
421 /* Set a NULL data pointer. */
422 tmp = build_constructor_single (type, field, null_pointer_node);
423 TREE_CONSTANT (tmp) = 1;
424 /* All other fields are ignored. */
426 return tmp;
430 /* Modify a descriptor such that the lbound of a given dimension is the value
431 specified. This also updates ubound and offset accordingly. */
433 void
434 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
435 int dim, tree new_lbound)
437 tree offs, ubound, lbound, stride;
438 tree diff, offs_diff;
440 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
442 offs = gfc_conv_descriptor_offset_get (desc);
443 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
444 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
445 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
447 /* Get difference (new - old) by which to shift stuff. */
448 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
449 new_lbound, lbound);
451 /* Shift ubound and offset accordingly. This has to be done before
452 updating the lbound, as they depend on the lbound expression! */
453 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
454 ubound, diff);
455 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
456 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
457 diff, stride);
458 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
459 offs, offs_diff);
460 gfc_conv_descriptor_offset_set (block, desc, offs);
462 /* Finally set lbound to value we want. */
463 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
467 /* Cleanup those #defines. */
469 #undef DATA_FIELD
470 #undef OFFSET_FIELD
471 #undef DTYPE_FIELD
472 #undef DIMENSION_FIELD
473 #undef CAF_TOKEN_FIELD
474 #undef STRIDE_SUBFIELD
475 #undef LBOUND_SUBFIELD
476 #undef UBOUND_SUBFIELD
479 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
480 flags & 1 = Main loop body.
481 flags & 2 = temp copy loop. */
483 void
484 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
486 for (; ss != gfc_ss_terminator; ss = ss->next)
487 ss->info->useflags = flags;
491 /* Free a gfc_ss chain. */
493 void
494 gfc_free_ss_chain (gfc_ss * ss)
496 gfc_ss *next;
498 while (ss != gfc_ss_terminator)
500 gcc_assert (ss != NULL);
501 next = ss->next;
502 gfc_free_ss (ss);
503 ss = next;
508 static void
509 free_ss_info (gfc_ss_info *ss_info)
511 int n;
513 ss_info->refcount--;
514 if (ss_info->refcount > 0)
515 return;
517 gcc_assert (ss_info->refcount == 0);
519 switch (ss_info->type)
521 case GFC_SS_SECTION:
522 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
523 if (ss_info->data.array.subscript[n])
524 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
525 break;
527 default:
528 break;
531 free (ss_info);
535 /* Free a SS. */
537 void
538 gfc_free_ss (gfc_ss * ss)
540 free_ss_info (ss->info);
541 free (ss);
545 /* Creates and initializes an array type gfc_ss struct. */
547 gfc_ss *
548 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
550 gfc_ss *ss;
551 gfc_ss_info *ss_info;
552 int i;
554 ss_info = gfc_get_ss_info ();
555 ss_info->refcount++;
556 ss_info->type = type;
557 ss_info->expr = expr;
559 ss = gfc_get_ss ();
560 ss->info = ss_info;
561 ss->next = next;
562 ss->dimen = dimen;
563 for (i = 0; i < ss->dimen; i++)
564 ss->dim[i] = i;
566 return ss;
570 /* Creates and initializes a temporary type gfc_ss struct. */
572 gfc_ss *
573 gfc_get_temp_ss (tree type, tree string_length, int dimen)
575 gfc_ss *ss;
576 gfc_ss_info *ss_info;
577 int i;
579 ss_info = gfc_get_ss_info ();
580 ss_info->refcount++;
581 ss_info->type = GFC_SS_TEMP;
582 ss_info->string_length = string_length;
583 ss_info->data.temp.type = type;
585 ss = gfc_get_ss ();
586 ss->info = ss_info;
587 ss->next = gfc_ss_terminator;
588 ss->dimen = dimen;
589 for (i = 0; i < ss->dimen; i++)
590 ss->dim[i] = i;
592 return ss;
596 /* Creates and initializes a scalar type gfc_ss struct. */
598 gfc_ss *
599 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
601 gfc_ss *ss;
602 gfc_ss_info *ss_info;
604 ss_info = gfc_get_ss_info ();
605 ss_info->refcount++;
606 ss_info->type = GFC_SS_SCALAR;
607 ss_info->expr = expr;
609 ss = gfc_get_ss ();
610 ss->info = ss_info;
611 ss->next = next;
613 return ss;
617 /* Free all the SS associated with a loop. */
619 void
620 gfc_cleanup_loop (gfc_loopinfo * loop)
622 gfc_loopinfo *loop_next, **ploop;
623 gfc_ss *ss;
624 gfc_ss *next;
626 ss = loop->ss;
627 while (ss != gfc_ss_terminator)
629 gcc_assert (ss != NULL);
630 next = ss->loop_chain;
631 gfc_free_ss (ss);
632 ss = next;
635 /* Remove reference to self in the parent loop. */
636 if (loop->parent)
637 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
638 if (*ploop == loop)
640 *ploop = loop->next;
641 break;
644 /* Free non-freed nested loops. */
645 for (loop = loop->nested; loop; loop = loop_next)
647 loop_next = loop->next;
648 gfc_cleanup_loop (loop);
649 free (loop);
654 static void
655 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
657 int n;
659 for (; ss != gfc_ss_terminator; ss = ss->next)
661 ss->loop = loop;
663 if (ss->info->type == GFC_SS_SCALAR
664 || ss->info->type == GFC_SS_REFERENCE
665 || ss->info->type == GFC_SS_TEMP)
666 continue;
668 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
669 if (ss->info->data.array.subscript[n] != NULL)
670 set_ss_loop (ss->info->data.array.subscript[n], loop);
675 /* Associate a SS chain with a loop. */
677 void
678 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
680 gfc_ss *ss;
681 gfc_loopinfo *nested_loop;
683 if (head == gfc_ss_terminator)
684 return;
686 set_ss_loop (head, loop);
688 ss = head;
689 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
691 if (ss->nested_ss)
693 nested_loop = ss->nested_ss->loop;
695 /* More than one ss can belong to the same loop. Hence, we add the
696 loop to the chain only if it is different from the previously
697 added one, to avoid duplicate nested loops. */
698 if (nested_loop != loop->nested)
700 gcc_assert (nested_loop->parent == NULL);
701 nested_loop->parent = loop;
703 gcc_assert (nested_loop->next == NULL);
704 nested_loop->next = loop->nested;
705 loop->nested = nested_loop;
707 else
708 gcc_assert (nested_loop->parent == loop);
711 if (ss->next == gfc_ss_terminator)
712 ss->loop_chain = loop->ss;
713 else
714 ss->loop_chain = ss->next;
716 gcc_assert (ss == gfc_ss_terminator);
717 loop->ss = head;
721 /* Generate an initializer for a static pointer or allocatable array. */
723 void
724 gfc_trans_static_array_pointer (gfc_symbol * sym)
726 tree type;
728 gcc_assert (TREE_STATIC (sym->backend_decl));
729 /* Just zero the data member. */
730 type = TREE_TYPE (sym->backend_decl);
731 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
735 /* If the bounds of SE's loop have not yet been set, see if they can be
736 determined from array spec AS, which is the array spec of a called
737 function. MAPPING maps the callee's dummy arguments to the values
738 that the caller is passing. Add any initialization and finalization
739 code to SE. */
741 void
742 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
743 gfc_se * se, gfc_array_spec * as)
745 int n, dim, total_dim;
746 gfc_se tmpse;
747 gfc_ss *ss;
748 tree lower;
749 tree upper;
750 tree tmp;
752 total_dim = 0;
754 if (!as || as->type != AS_EXPLICIT)
755 return;
757 for (ss = se->ss; ss; ss = ss->parent)
759 total_dim += ss->loop->dimen;
760 for (n = 0; n < ss->loop->dimen; n++)
762 /* The bound is known, nothing to do. */
763 if (ss->loop->to[n] != NULL_TREE)
764 continue;
766 dim = ss->dim[n];
767 gcc_assert (dim < as->rank);
768 gcc_assert (ss->loop->dimen <= as->rank);
770 /* Evaluate the lower bound. */
771 gfc_init_se (&tmpse, NULL);
772 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
773 gfc_add_block_to_block (&se->pre, &tmpse.pre);
774 gfc_add_block_to_block (&se->post, &tmpse.post);
775 lower = fold_convert (gfc_array_index_type, tmpse.expr);
777 /* ...and the upper bound. */
778 gfc_init_se (&tmpse, NULL);
779 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
780 gfc_add_block_to_block (&se->pre, &tmpse.pre);
781 gfc_add_block_to_block (&se->post, &tmpse.post);
782 upper = fold_convert (gfc_array_index_type, tmpse.expr);
784 /* Set the upper bound of the loop to UPPER - LOWER. */
785 tmp = fold_build2_loc (input_location, MINUS_EXPR,
786 gfc_array_index_type, upper, lower);
787 tmp = gfc_evaluate_now (tmp, &se->pre);
788 ss->loop->to[n] = tmp;
792 gcc_assert (total_dim == as->rank);
796 /* Generate code to allocate an array temporary, or create a variable to
797 hold the data. If size is NULL, zero the descriptor so that the
798 callee will allocate the array. If DEALLOC is true, also generate code to
799 free the array afterwards.
801 If INITIAL is not NULL, it is packed using internal_pack and the result used
802 as data instead of allocating a fresh, unitialized area of memory.
804 Initialization code is added to PRE and finalization code to POST.
805 DYNAMIC is true if the caller may want to extend the array later
806 using realloc. This prevents us from putting the array on the stack. */
808 static void
809 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
810 gfc_array_info * info, tree size, tree nelem,
811 tree initial, bool dynamic, bool dealloc)
813 tree tmp;
814 tree desc;
815 bool onstack;
817 desc = info->descriptor;
818 info->offset = gfc_index_zero_node;
819 if (size == NULL_TREE || integer_zerop (size))
821 /* A callee allocated array. */
822 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
823 onstack = FALSE;
825 else
827 /* Allocate the temporary. */
828 onstack = !dynamic && initial == NULL_TREE
829 && (gfc_option.flag_stack_arrays
830 || gfc_can_put_var_on_stack (size));
832 if (onstack)
834 /* Make a temporary variable to hold the data. */
835 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
836 nelem, gfc_index_one_node);
837 tmp = gfc_evaluate_now (tmp, pre);
838 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
839 tmp);
840 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
841 tmp);
842 tmp = gfc_create_var (tmp, "A");
843 /* If we're here only because of -fstack-arrays we have to
844 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
845 if (!gfc_can_put_var_on_stack (size))
846 gfc_add_expr_to_block (pre,
847 fold_build1_loc (input_location,
848 DECL_EXPR, TREE_TYPE (tmp),
849 tmp));
850 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
851 gfc_conv_descriptor_data_set (pre, desc, tmp);
853 else
855 /* Allocate memory to hold the data or call internal_pack. */
856 if (initial == NULL_TREE)
858 tmp = gfc_call_malloc (pre, NULL, size);
859 tmp = gfc_evaluate_now (tmp, pre);
861 else
863 tree packed;
864 tree source_data;
865 tree was_packed;
866 stmtblock_t do_copying;
868 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
869 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
870 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
871 tmp = gfc_get_element_type (tmp);
872 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
873 packed = gfc_create_var (build_pointer_type (tmp), "data");
875 tmp = build_call_expr_loc (input_location,
876 gfor_fndecl_in_pack, 1, initial);
877 tmp = fold_convert (TREE_TYPE (packed), tmp);
878 gfc_add_modify (pre, packed, tmp);
880 tmp = build_fold_indirect_ref_loc (input_location,
881 initial);
882 source_data = gfc_conv_descriptor_data_get (tmp);
884 /* internal_pack may return source->data without any allocation
885 or copying if it is already packed. If that's the case, we
886 need to allocate and copy manually. */
888 gfc_start_block (&do_copying);
889 tmp = gfc_call_malloc (&do_copying, NULL, size);
890 tmp = fold_convert (TREE_TYPE (packed), tmp);
891 gfc_add_modify (&do_copying, packed, tmp);
892 tmp = gfc_build_memcpy_call (packed, source_data, size);
893 gfc_add_expr_to_block (&do_copying, tmp);
895 was_packed = fold_build2_loc (input_location, EQ_EXPR,
896 boolean_type_node, packed,
897 source_data);
898 tmp = gfc_finish_block (&do_copying);
899 tmp = build3_v (COND_EXPR, was_packed, tmp,
900 build_empty_stmt (input_location));
901 gfc_add_expr_to_block (pre, tmp);
903 tmp = fold_convert (pvoid_type_node, packed);
906 gfc_conv_descriptor_data_set (pre, desc, tmp);
909 info->data = gfc_conv_descriptor_data_get (desc);
911 /* The offset is zero because we create temporaries with a zero
912 lower bound. */
913 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
915 if (dealloc && !onstack)
917 /* Free the temporary. */
918 tmp = gfc_conv_descriptor_data_get (desc);
919 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
920 gfc_add_expr_to_block (post, tmp);
925 /* Get the scalarizer array dimension corresponding to actual array dimension
926 given by ARRAY_DIM.
928 For example, if SS represents the array ref a(1,:,:,1), it is a
929 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
930 and 1 for ARRAY_DIM=2.
931 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
932 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
933 ARRAY_DIM=3.
934 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
935 array. If called on the inner ss, the result would be respectively 0,1,2 for
936 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
937 for ARRAY_DIM=1,2. */
939 static int
940 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
942 int array_ref_dim;
943 int n;
945 array_ref_dim = 0;
947 for (; ss; ss = ss->parent)
948 for (n = 0; n < ss->dimen; n++)
949 if (ss->dim[n] < array_dim)
950 array_ref_dim++;
952 return array_ref_dim;
956 static gfc_ss *
957 innermost_ss (gfc_ss *ss)
959 while (ss->nested_ss != NULL)
960 ss = ss->nested_ss;
962 return ss;
967 /* Get the array reference dimension corresponding to the given loop dimension.
968 It is different from the true array dimension given by the dim array in
969 the case of a partial array reference (i.e. a(:,:,1,:) for example)
970 It is different from the loop dimension in the case of a transposed array.
973 static int
974 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
976 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
977 ss->dim[loop_dim]);
981 /* Generate code to create and initialize the descriptor for a temporary
982 array. This is used for both temporaries needed by the scalarizer, and
983 functions returning arrays. Adjusts the loop variables to be
984 zero-based, and calculates the loop bounds for callee allocated arrays.
985 Allocate the array unless it's callee allocated (we have a callee
986 allocated array if 'callee_alloc' is true, or if loop->to[n] is
987 NULL_TREE for any n). Also fills in the descriptor, data and offset
988 fields of info if known. Returns the size of the array, or NULL for a
989 callee allocated array.
991 'eltype' == NULL signals that the temporary should be a class object.
992 The 'initial' expression is used to obtain the size of the dynamic
993 type; otherwise the allocation and initialisation proceeds as for any
994 other expression
996 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
997 gfc_trans_allocate_array_storage. */
999 tree
1000 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
1001 tree eltype, tree initial, bool dynamic,
1002 bool dealloc, bool callee_alloc, locus * where)
1004 gfc_loopinfo *loop;
1005 gfc_ss *s;
1006 gfc_array_info *info;
1007 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
1008 tree type;
1009 tree desc;
1010 tree tmp;
1011 tree size;
1012 tree nelem;
1013 tree cond;
1014 tree or_expr;
1015 tree class_expr = NULL_TREE;
1016 int n, dim, tmp_dim;
1017 int total_dim = 0;
1019 /* This signals a class array for which we need the size of the
1020 dynamic type. Generate an eltype and then the class expression. */
1021 if (eltype == NULL_TREE && initial)
1023 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1024 class_expr = build_fold_indirect_ref_loc (input_location, initial);
1025 eltype = TREE_TYPE (class_expr);
1026 eltype = gfc_get_element_type (eltype);
1027 /* Obtain the structure (class) expression. */
1028 class_expr = TREE_OPERAND (class_expr, 0);
1029 gcc_assert (class_expr);
1032 memset (from, 0, sizeof (from));
1033 memset (to, 0, sizeof (to));
1035 info = &ss->info->data.array;
1037 gcc_assert (ss->dimen > 0);
1038 gcc_assert (ss->loop->dimen == ss->dimen);
1040 if (gfc_option.warn_array_temp && where)
1041 gfc_warning ("Creating array temporary at %L", where);
1043 /* Set the lower bound to zero. */
1044 for (s = ss; s; s = s->parent)
1046 loop = s->loop;
1048 total_dim += loop->dimen;
1049 for (n = 0; n < loop->dimen; n++)
1051 dim = s->dim[n];
1053 /* Callee allocated arrays may not have a known bound yet. */
1054 if (loop->to[n])
1055 loop->to[n] = gfc_evaluate_now (
1056 fold_build2_loc (input_location, MINUS_EXPR,
1057 gfc_array_index_type,
1058 loop->to[n], loop->from[n]),
1059 pre);
1060 loop->from[n] = gfc_index_zero_node;
1062 /* We have just changed the loop bounds, we must clear the
1063 corresponding specloop, so that delta calculation is not skipped
1064 later in gfc_set_delta. */
1065 loop->specloop[n] = NULL;
1067 /* We are constructing the temporary's descriptor based on the loop
1068 dimensions. As the dimensions may be accessed in arbitrary order
1069 (think of transpose) the size taken from the n'th loop may not map
1070 to the n'th dimension of the array. We need to reconstruct loop
1071 infos in the right order before using it to set the descriptor
1072 bounds. */
1073 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1074 from[tmp_dim] = loop->from[n];
1075 to[tmp_dim] = loop->to[n];
1077 info->delta[dim] = gfc_index_zero_node;
1078 info->start[dim] = gfc_index_zero_node;
1079 info->end[dim] = gfc_index_zero_node;
1080 info->stride[dim] = gfc_index_one_node;
1084 /* Initialize the descriptor. */
1085 type =
1086 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1087 GFC_ARRAY_UNKNOWN, true);
1088 desc = gfc_create_var (type, "atmp");
1089 GFC_DECL_PACKED_ARRAY (desc) = 1;
1091 info->descriptor = desc;
1092 size = gfc_index_one_node;
1094 /* Fill in the array dtype. */
1095 tmp = gfc_conv_descriptor_dtype (desc);
1096 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1099 Fill in the bounds and stride. This is a packed array, so:
1101 size = 1;
1102 for (n = 0; n < rank; n++)
1104 stride[n] = size
1105 delta = ubound[n] + 1 - lbound[n];
1106 size = size * delta;
1108 size = size * sizeof(element);
1111 or_expr = NULL_TREE;
1113 /* If there is at least one null loop->to[n], it is a callee allocated
1114 array. */
1115 for (n = 0; n < total_dim; n++)
1116 if (to[n] == NULL_TREE)
1118 size = NULL_TREE;
1119 break;
1122 if (size == NULL_TREE)
1123 for (s = ss; s; s = s->parent)
1124 for (n = 0; n < s->loop->dimen; n++)
1126 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
1128 /* For a callee allocated array express the loop bounds in terms
1129 of the descriptor fields. */
1130 tmp = fold_build2_loc (input_location,
1131 MINUS_EXPR, gfc_array_index_type,
1132 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1133 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1134 s->loop->to[n] = tmp;
1136 else
1138 for (n = 0; n < total_dim; n++)
1140 /* Store the stride and bound components in the descriptor. */
1141 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1143 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1144 gfc_index_zero_node);
1146 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1148 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1149 gfc_array_index_type,
1150 to[n], gfc_index_one_node);
1152 /* Check whether the size for this dimension is negative. */
1153 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1154 tmp, gfc_index_zero_node);
1155 cond = gfc_evaluate_now (cond, pre);
1157 if (n == 0)
1158 or_expr = cond;
1159 else
1160 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1161 boolean_type_node, or_expr, cond);
1163 size = fold_build2_loc (input_location, MULT_EXPR,
1164 gfc_array_index_type, size, tmp);
1165 size = gfc_evaluate_now (size, pre);
1169 /* Get the size of the array. */
1170 if (size && !callee_alloc)
1172 tree elemsize;
1173 /* If or_expr is true, then the extent in at least one
1174 dimension is zero and the size is set to zero. */
1175 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1176 or_expr, gfc_index_zero_node, size);
1178 nelem = size;
1179 if (class_expr == NULL_TREE)
1180 elemsize = fold_convert (gfc_array_index_type,
1181 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1182 else
1183 elemsize = gfc_vtable_size_get (class_expr);
1185 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1186 size, elemsize);
1188 else
1190 nelem = size;
1191 size = NULL_TREE;
1194 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1195 dynamic, dealloc);
1197 while (ss->parent)
1198 ss = ss->parent;
1200 if (ss->dimen > ss->loop->temp_dim)
1201 ss->loop->temp_dim = ss->dimen;
1203 return size;
1207 /* Return the number of iterations in a loop that starts at START,
1208 ends at END, and has step STEP. */
1210 static tree
1211 gfc_get_iteration_count (tree start, tree end, tree step)
1213 tree tmp;
1214 tree type;
1216 type = TREE_TYPE (step);
1217 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1218 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1219 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1220 build_int_cst (type, 1));
1221 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1222 build_int_cst (type, 0));
1223 return fold_convert (gfc_array_index_type, tmp);
1227 /* Extend the data in array DESC by EXTRA elements. */
1229 static void
1230 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1232 tree arg0, arg1;
1233 tree tmp;
1234 tree size;
1235 tree ubound;
1237 if (integer_zerop (extra))
1238 return;
1240 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1242 /* Add EXTRA to the upper bound. */
1243 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1244 ubound, extra);
1245 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1247 /* Get the value of the current data pointer. */
1248 arg0 = gfc_conv_descriptor_data_get (desc);
1250 /* Calculate the new array size. */
1251 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1252 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1253 ubound, gfc_index_one_node);
1254 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1255 fold_convert (size_type_node, tmp),
1256 fold_convert (size_type_node, size));
1258 /* Call the realloc() function. */
1259 tmp = gfc_call_realloc (pblock, arg0, arg1);
1260 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1264 /* Return true if the bounds of iterator I can only be determined
1265 at run time. */
1267 static inline bool
1268 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1270 return (i->start->expr_type != EXPR_CONSTANT
1271 || i->end->expr_type != EXPR_CONSTANT
1272 || i->step->expr_type != EXPR_CONSTANT);
1276 /* Split the size of constructor element EXPR into the sum of two terms,
1277 one of which can be determined at compile time and one of which must
1278 be calculated at run time. Set *SIZE to the former and return true
1279 if the latter might be nonzero. */
1281 static bool
1282 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1284 if (expr->expr_type == EXPR_ARRAY)
1285 return gfc_get_array_constructor_size (size, expr->value.constructor);
1286 else if (expr->rank > 0)
1288 /* Calculate everything at run time. */
1289 mpz_set_ui (*size, 0);
1290 return true;
1292 else
1294 /* A single element. */
1295 mpz_set_ui (*size, 1);
1296 return false;
1301 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1302 of array constructor C. */
1304 static bool
1305 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1307 gfc_constructor *c;
1308 gfc_iterator *i;
1309 mpz_t val;
1310 mpz_t len;
1311 bool dynamic;
1313 mpz_set_ui (*size, 0);
1314 mpz_init (len);
1315 mpz_init (val);
1317 dynamic = false;
1318 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1320 i = c->iterator;
1321 if (i && gfc_iterator_has_dynamic_bounds (i))
1322 dynamic = true;
1323 else
1325 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1326 if (i)
1328 /* Multiply the static part of the element size by the
1329 number of iterations. */
1330 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1331 mpz_fdiv_q (val, val, i->step->value.integer);
1332 mpz_add_ui (val, val, 1);
1333 if (mpz_sgn (val) > 0)
1334 mpz_mul (len, len, val);
1335 else
1336 mpz_set_ui (len, 0);
1338 mpz_add (*size, *size, len);
1341 mpz_clear (len);
1342 mpz_clear (val);
1343 return dynamic;
1347 /* Make sure offset is a variable. */
1349 static void
1350 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1351 tree * offsetvar)
1353 /* We should have already created the offset variable. We cannot
1354 create it here because we may be in an inner scope. */
1355 gcc_assert (*offsetvar != NULL_TREE);
1356 gfc_add_modify (pblock, *offsetvar, *poffset);
1357 *poffset = *offsetvar;
1358 TREE_USED (*offsetvar) = 1;
1362 /* Variables needed for bounds-checking. */
1363 static bool first_len;
1364 static tree first_len_val;
1365 static bool typespec_chararray_ctor;
1367 static void
1368 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1369 tree offset, gfc_se * se, gfc_expr * expr)
1371 tree tmp;
1373 gfc_conv_expr (se, expr);
1375 /* Store the value. */
1376 tmp = build_fold_indirect_ref_loc (input_location,
1377 gfc_conv_descriptor_data_get (desc));
1378 tmp = gfc_build_array_ref (tmp, offset, NULL);
1380 if (expr->ts.type == BT_CHARACTER)
1382 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1383 tree esize;
1385 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1386 esize = fold_convert (gfc_charlen_type_node, esize);
1387 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1388 gfc_charlen_type_node, esize,
1389 build_int_cst (gfc_charlen_type_node,
1390 gfc_character_kinds[i].bit_size / 8));
1392 gfc_conv_string_parameter (se);
1393 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1395 /* The temporary is an array of pointers. */
1396 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1397 gfc_add_modify (&se->pre, tmp, se->expr);
1399 else
1401 /* The temporary is an array of string values. */
1402 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1403 /* We know the temporary and the value will be the same length,
1404 so can use memcpy. */
1405 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1406 se->string_length, se->expr, expr->ts.kind);
1408 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1410 if (first_len)
1412 gfc_add_modify (&se->pre, first_len_val,
1413 se->string_length);
1414 first_len = false;
1416 else
1418 /* Verify that all constructor elements are of the same
1419 length. */
1420 tree cond = fold_build2_loc (input_location, NE_EXPR,
1421 boolean_type_node, first_len_val,
1422 se->string_length);
1423 gfc_trans_runtime_check
1424 (true, false, cond, &se->pre, &expr->where,
1425 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1426 fold_convert (long_integer_type_node, first_len_val),
1427 fold_convert (long_integer_type_node, se->string_length));
1431 else
1433 /* TODO: Should the frontend already have done this conversion? */
1434 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1435 gfc_add_modify (&se->pre, tmp, se->expr);
1438 gfc_add_block_to_block (pblock, &se->pre);
1439 gfc_add_block_to_block (pblock, &se->post);
1443 /* Add the contents of an array to the constructor. DYNAMIC is as for
1444 gfc_trans_array_constructor_value. */
1446 static void
1447 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1448 tree type ATTRIBUTE_UNUSED,
1449 tree desc, gfc_expr * expr,
1450 tree * poffset, tree * offsetvar,
1451 bool dynamic)
1453 gfc_se se;
1454 gfc_ss *ss;
1455 gfc_loopinfo loop;
1456 stmtblock_t body;
1457 tree tmp;
1458 tree size;
1459 int n;
1461 /* We need this to be a variable so we can increment it. */
1462 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1464 gfc_init_se (&se, NULL);
1466 /* Walk the array expression. */
1467 ss = gfc_walk_expr (expr);
1468 gcc_assert (ss != gfc_ss_terminator);
1470 /* Initialize the scalarizer. */
1471 gfc_init_loopinfo (&loop);
1472 gfc_add_ss_to_loop (&loop, ss);
1474 /* Initialize the loop. */
1475 gfc_conv_ss_startstride (&loop);
1476 gfc_conv_loop_setup (&loop, &expr->where);
1478 /* Make sure the constructed array has room for the new data. */
1479 if (dynamic)
1481 /* Set SIZE to the total number of elements in the subarray. */
1482 size = gfc_index_one_node;
1483 for (n = 0; n < loop.dimen; n++)
1485 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1486 gfc_index_one_node);
1487 size = fold_build2_loc (input_location, MULT_EXPR,
1488 gfc_array_index_type, size, tmp);
1491 /* Grow the constructed array by SIZE elements. */
1492 gfc_grow_array (&loop.pre, desc, size);
1495 /* Make the loop body. */
1496 gfc_mark_ss_chain_used (ss, 1);
1497 gfc_start_scalarized_body (&loop, &body);
1498 gfc_copy_loopinfo_to_se (&se, &loop);
1499 se.ss = ss;
1501 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1502 gcc_assert (se.ss == gfc_ss_terminator);
1504 /* Increment the offset. */
1505 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1506 *poffset, gfc_index_one_node);
1507 gfc_add_modify (&body, *poffset, tmp);
1509 /* Finish the loop. */
1510 gfc_trans_scalarizing_loops (&loop, &body);
1511 gfc_add_block_to_block (&loop.pre, &loop.post);
1512 tmp = gfc_finish_block (&loop.pre);
1513 gfc_add_expr_to_block (pblock, tmp);
1515 gfc_cleanup_loop (&loop);
1519 /* Assign the values to the elements of an array constructor. DYNAMIC
1520 is true if descriptor DESC only contains enough data for the static
1521 size calculated by gfc_get_array_constructor_size. When true, memory
1522 for the dynamic parts must be allocated using realloc. */
1524 static void
1525 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1526 tree desc, gfc_constructor_base base,
1527 tree * poffset, tree * offsetvar,
1528 bool dynamic)
1530 tree tmp;
1531 tree start = NULL_TREE;
1532 tree end = NULL_TREE;
1533 tree step = NULL_TREE;
1534 stmtblock_t body;
1535 gfc_se se;
1536 mpz_t size;
1537 gfc_constructor *c;
1539 tree shadow_loopvar = NULL_TREE;
1540 gfc_saved_var saved_loopvar;
1542 mpz_init (size);
1543 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1545 /* If this is an iterator or an array, the offset must be a variable. */
1546 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1547 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1549 /* Shadowing the iterator avoids changing its value and saves us from
1550 keeping track of it. Further, it makes sure that there's always a
1551 backend-decl for the symbol, even if there wasn't one before,
1552 e.g. in the case of an iterator that appears in a specification
1553 expression in an interface mapping. */
1554 if (c->iterator)
1556 gfc_symbol *sym;
1557 tree type;
1559 /* Evaluate loop bounds before substituting the loop variable
1560 in case they depend on it. Such a case is invalid, but it is
1561 not more expensive to do the right thing here.
1562 See PR 44354. */
1563 gfc_init_se (&se, NULL);
1564 gfc_conv_expr_val (&se, c->iterator->start);
1565 gfc_add_block_to_block (pblock, &se.pre);
1566 start = gfc_evaluate_now (se.expr, pblock);
1568 gfc_init_se (&se, NULL);
1569 gfc_conv_expr_val (&se, c->iterator->end);
1570 gfc_add_block_to_block (pblock, &se.pre);
1571 end = gfc_evaluate_now (se.expr, pblock);
1573 gfc_init_se (&se, NULL);
1574 gfc_conv_expr_val (&se, c->iterator->step);
1575 gfc_add_block_to_block (pblock, &se.pre);
1576 step = gfc_evaluate_now (se.expr, pblock);
1578 sym = c->iterator->var->symtree->n.sym;
1579 type = gfc_typenode_for_spec (&sym->ts);
1581 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1582 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1585 gfc_start_block (&body);
1587 if (c->expr->expr_type == EXPR_ARRAY)
1589 /* Array constructors can be nested. */
1590 gfc_trans_array_constructor_value (&body, type, desc,
1591 c->expr->value.constructor,
1592 poffset, offsetvar, dynamic);
1594 else if (c->expr->rank > 0)
1596 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1597 poffset, offsetvar, dynamic);
1599 else
1601 /* This code really upsets the gimplifier so don't bother for now. */
1602 gfc_constructor *p;
1603 HOST_WIDE_INT n;
1604 HOST_WIDE_INT size;
1606 p = c;
1607 n = 0;
1608 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1610 p = gfc_constructor_next (p);
1611 n++;
1613 if (n < 4)
1615 /* Scalar values. */
1616 gfc_init_se (&se, NULL);
1617 gfc_trans_array_ctor_element (&body, desc, *poffset,
1618 &se, c->expr);
1620 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1621 gfc_array_index_type,
1622 *poffset, gfc_index_one_node);
1624 else
1626 /* Collect multiple scalar constants into a constructor. */
1627 vec<constructor_elt, va_gc> *v = NULL;
1628 tree init;
1629 tree bound;
1630 tree tmptype;
1631 HOST_WIDE_INT idx = 0;
1633 p = c;
1634 /* Count the number of consecutive scalar constants. */
1635 while (p && !(p->iterator
1636 || p->expr->expr_type != EXPR_CONSTANT))
1638 gfc_init_se (&se, NULL);
1639 gfc_conv_constant (&se, p->expr);
1641 if (c->expr->ts.type != BT_CHARACTER)
1642 se.expr = fold_convert (type, se.expr);
1643 /* For constant character array constructors we build
1644 an array of pointers. */
1645 else if (POINTER_TYPE_P (type))
1646 se.expr = gfc_build_addr_expr
1647 (gfc_get_pchar_type (p->expr->ts.kind),
1648 se.expr);
1650 CONSTRUCTOR_APPEND_ELT (v,
1651 build_int_cst (gfc_array_index_type,
1652 idx++),
1653 se.expr);
1654 c = p;
1655 p = gfc_constructor_next (p);
1658 bound = size_int (n - 1);
1659 /* Create an array type to hold them. */
1660 tmptype = build_range_type (gfc_array_index_type,
1661 gfc_index_zero_node, bound);
1662 tmptype = build_array_type (type, tmptype);
1664 init = build_constructor (tmptype, v);
1665 TREE_CONSTANT (init) = 1;
1666 TREE_STATIC (init) = 1;
1667 /* Create a static variable to hold the data. */
1668 tmp = gfc_create_var (tmptype, "data");
1669 TREE_STATIC (tmp) = 1;
1670 TREE_CONSTANT (tmp) = 1;
1671 TREE_READONLY (tmp) = 1;
1672 DECL_INITIAL (tmp) = init;
1673 init = tmp;
1675 /* Use BUILTIN_MEMCPY to assign the values. */
1676 tmp = gfc_conv_descriptor_data_get (desc);
1677 tmp = build_fold_indirect_ref_loc (input_location,
1678 tmp);
1679 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1680 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1681 init = gfc_build_addr_expr (NULL_TREE, init);
1683 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1684 bound = build_int_cst (size_type_node, n * size);
1685 tmp = build_call_expr_loc (input_location,
1686 builtin_decl_explicit (BUILT_IN_MEMCPY),
1687 3, tmp, init, bound);
1688 gfc_add_expr_to_block (&body, tmp);
1690 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1691 gfc_array_index_type, *poffset,
1692 build_int_cst (gfc_array_index_type, n));
1694 if (!INTEGER_CST_P (*poffset))
1696 gfc_add_modify (&body, *offsetvar, *poffset);
1697 *poffset = *offsetvar;
1701 /* The frontend should already have done any expansions
1702 at compile-time. */
1703 if (!c->iterator)
1705 /* Pass the code as is. */
1706 tmp = gfc_finish_block (&body);
1707 gfc_add_expr_to_block (pblock, tmp);
1709 else
1711 /* Build the implied do-loop. */
1712 stmtblock_t implied_do_block;
1713 tree cond;
1714 tree exit_label;
1715 tree loopbody;
1716 tree tmp2;
1718 loopbody = gfc_finish_block (&body);
1720 /* Create a new block that holds the implied-do loop. A temporary
1721 loop-variable is used. */
1722 gfc_start_block(&implied_do_block);
1724 /* Initialize the loop. */
1725 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
1727 /* If this array expands dynamically, and the number of iterations
1728 is not constant, we won't have allocated space for the static
1729 part of C->EXPR's size. Do that now. */
1730 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1732 /* Get the number of iterations. */
1733 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1735 /* Get the static part of C->EXPR's size. */
1736 gfc_get_array_constructor_element_size (&size, c->expr);
1737 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1739 /* Grow the array by TMP * TMP2 elements. */
1740 tmp = fold_build2_loc (input_location, MULT_EXPR,
1741 gfc_array_index_type, tmp, tmp2);
1742 gfc_grow_array (&implied_do_block, desc, tmp);
1745 /* Generate the loop body. */
1746 exit_label = gfc_build_label_decl (NULL_TREE);
1747 gfc_start_block (&body);
1749 /* Generate the exit condition. Depending on the sign of
1750 the step variable we have to generate the correct
1751 comparison. */
1752 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1753 step, build_int_cst (TREE_TYPE (step), 0));
1754 cond = fold_build3_loc (input_location, COND_EXPR,
1755 boolean_type_node, tmp,
1756 fold_build2_loc (input_location, GT_EXPR,
1757 boolean_type_node, shadow_loopvar, end),
1758 fold_build2_loc (input_location, LT_EXPR,
1759 boolean_type_node, shadow_loopvar, end));
1760 tmp = build1_v (GOTO_EXPR, exit_label);
1761 TREE_USED (exit_label) = 1;
1762 tmp = build3_v (COND_EXPR, cond, tmp,
1763 build_empty_stmt (input_location));
1764 gfc_add_expr_to_block (&body, tmp);
1766 /* The main loop body. */
1767 gfc_add_expr_to_block (&body, loopbody);
1769 /* Increase loop variable by step. */
1770 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1771 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1772 step);
1773 gfc_add_modify (&body, shadow_loopvar, tmp);
1775 /* Finish the loop. */
1776 tmp = gfc_finish_block (&body);
1777 tmp = build1_v (LOOP_EXPR, tmp);
1778 gfc_add_expr_to_block (&implied_do_block, tmp);
1780 /* Add the exit label. */
1781 tmp = build1_v (LABEL_EXPR, exit_label);
1782 gfc_add_expr_to_block (&implied_do_block, tmp);
1784 /* Finish the implied-do loop. */
1785 tmp = gfc_finish_block(&implied_do_block);
1786 gfc_add_expr_to_block(pblock, tmp);
1788 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1791 mpz_clear (size);
1795 /* A catch-all to obtain the string length for anything that is not
1796 a substring of non-constant length, a constant, array or variable. */
1798 static void
1799 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1801 gfc_se se;
1803 /* Don't bother if we already know the length is a constant. */
1804 if (*len && INTEGER_CST_P (*len))
1805 return;
1807 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1808 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1810 /* This is easy. */
1811 gfc_conv_const_charlen (e->ts.u.cl);
1812 *len = e->ts.u.cl->backend_decl;
1814 else
1816 /* Otherwise, be brutal even if inefficient. */
1817 gfc_init_se (&se, NULL);
1819 /* No function call, in case of side effects. */
1820 se.no_function_call = 1;
1821 if (e->rank == 0)
1822 gfc_conv_expr (&se, e);
1823 else
1824 gfc_conv_expr_descriptor (&se, e);
1826 /* Fix the value. */
1827 *len = gfc_evaluate_now (se.string_length, &se.pre);
1829 gfc_add_block_to_block (block, &se.pre);
1830 gfc_add_block_to_block (block, &se.post);
1832 e->ts.u.cl->backend_decl = *len;
1837 /* Figure out the string length of a variable reference expression.
1838 Used by get_array_ctor_strlen. */
1840 static void
1841 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
1843 gfc_ref *ref;
1844 gfc_typespec *ts;
1845 mpz_t char_len;
1847 /* Don't bother if we already know the length is a constant. */
1848 if (*len && INTEGER_CST_P (*len))
1849 return;
1851 ts = &expr->symtree->n.sym->ts;
1852 for (ref = expr->ref; ref; ref = ref->next)
1854 switch (ref->type)
1856 case REF_ARRAY:
1857 /* Array references don't change the string length. */
1858 break;
1860 case REF_COMPONENT:
1861 /* Use the length of the component. */
1862 ts = &ref->u.c.component->ts;
1863 break;
1865 case REF_SUBSTRING:
1866 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1867 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1869 /* Note that this might evaluate expr. */
1870 get_array_ctor_all_strlen (block, expr, len);
1871 return;
1873 mpz_init_set_ui (char_len, 1);
1874 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1875 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1876 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1877 *len = convert (gfc_charlen_type_node, *len);
1878 mpz_clear (char_len);
1879 return;
1881 default:
1882 gcc_unreachable ();
1886 *len = ts->u.cl->backend_decl;
1890 /* Figure out the string length of a character array constructor.
1891 If len is NULL, don't calculate the length; this happens for recursive calls
1892 when a sub-array-constructor is an element but not at the first position,
1893 so when we're not interested in the length.
1894 Returns TRUE if all elements are character constants. */
1896 bool
1897 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
1899 gfc_constructor *c;
1900 bool is_const;
1902 is_const = TRUE;
1904 if (gfc_constructor_first (base) == NULL)
1906 if (len)
1907 *len = build_int_cstu (gfc_charlen_type_node, 0);
1908 return is_const;
1911 /* Loop over all constructor elements to find out is_const, but in len we
1912 want to store the length of the first, not the last, element. We can
1913 of course exit the loop as soon as is_const is found to be false. */
1914 for (c = gfc_constructor_first (base);
1915 c && is_const; c = gfc_constructor_next (c))
1917 switch (c->expr->expr_type)
1919 case EXPR_CONSTANT:
1920 if (len && !(*len && INTEGER_CST_P (*len)))
1921 *len = build_int_cstu (gfc_charlen_type_node,
1922 c->expr->value.character.length);
1923 break;
1925 case EXPR_ARRAY:
1926 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1927 is_const = false;
1928 break;
1930 case EXPR_VARIABLE:
1931 is_const = false;
1932 if (len)
1933 get_array_ctor_var_strlen (block, c->expr, len);
1934 break;
1936 default:
1937 is_const = false;
1938 if (len)
1939 get_array_ctor_all_strlen (block, c->expr, len);
1940 break;
1943 /* After the first iteration, we don't want the length modified. */
1944 len = NULL;
1947 return is_const;
1950 /* Check whether the array constructor C consists entirely of constant
1951 elements, and if so returns the number of those elements, otherwise
1952 return zero. Note, an empty or NULL array constructor returns zero. */
1954 unsigned HOST_WIDE_INT
1955 gfc_constant_array_constructor_p (gfc_constructor_base base)
1957 unsigned HOST_WIDE_INT nelem = 0;
1959 gfc_constructor *c = gfc_constructor_first (base);
1960 while (c)
1962 if (c->iterator
1963 || c->expr->rank > 0
1964 || c->expr->expr_type != EXPR_CONSTANT)
1965 return 0;
1966 c = gfc_constructor_next (c);
1967 nelem++;
1969 return nelem;
1973 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1974 and the tree type of it's elements, TYPE, return a static constant
1975 variable that is compile-time initialized. */
1977 tree
1978 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1980 tree tmptype, init, tmp;
1981 HOST_WIDE_INT nelem;
1982 gfc_constructor *c;
1983 gfc_array_spec as;
1984 gfc_se se;
1985 int i;
1986 vec<constructor_elt, va_gc> *v = NULL;
1988 /* First traverse the constructor list, converting the constants
1989 to tree to build an initializer. */
1990 nelem = 0;
1991 c = gfc_constructor_first (expr->value.constructor);
1992 while (c)
1994 gfc_init_se (&se, NULL);
1995 gfc_conv_constant (&se, c->expr);
1996 if (c->expr->ts.type != BT_CHARACTER)
1997 se.expr = fold_convert (type, se.expr);
1998 else if (POINTER_TYPE_P (type))
1999 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2000 se.expr);
2001 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2002 se.expr);
2003 c = gfc_constructor_next (c);
2004 nelem++;
2007 /* Next determine the tree type for the array. We use the gfortran
2008 front-end's gfc_get_nodesc_array_type in order to create a suitable
2009 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2011 memset (&as, 0, sizeof (gfc_array_spec));
2013 as.rank = expr->rank;
2014 as.type = AS_EXPLICIT;
2015 if (!expr->shape)
2017 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2018 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2019 NULL, nelem - 1);
2021 else
2022 for (i = 0; i < expr->rank; i++)
2024 int tmp = (int) mpz_get_si (expr->shape[i]);
2025 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2026 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2027 NULL, tmp - 1);
2030 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
2032 /* as is not needed anymore. */
2033 for (i = 0; i < as.rank + as.corank; i++)
2035 gfc_free_expr (as.lower[i]);
2036 gfc_free_expr (as.upper[i]);
2039 init = build_constructor (tmptype, v);
2041 TREE_CONSTANT (init) = 1;
2042 TREE_STATIC (init) = 1;
2044 tmp = gfc_create_var (tmptype, "A");
2045 TREE_STATIC (tmp) = 1;
2046 TREE_CONSTANT (tmp) = 1;
2047 TREE_READONLY (tmp) = 1;
2048 DECL_INITIAL (tmp) = init;
2050 return tmp;
2054 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2055 This mostly initializes the scalarizer state info structure with the
2056 appropriate values to directly use the array created by the function
2057 gfc_build_constant_array_constructor. */
2059 static void
2060 trans_constant_array_constructor (gfc_ss * ss, tree type)
2062 gfc_array_info *info;
2063 tree tmp;
2064 int i;
2066 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
2068 info = &ss->info->data.array;
2070 info->descriptor = tmp;
2071 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
2072 info->offset = gfc_index_zero_node;
2074 for (i = 0; i < ss->dimen; i++)
2076 info->delta[i] = gfc_index_zero_node;
2077 info->start[i] = gfc_index_zero_node;
2078 info->end[i] = gfc_index_zero_node;
2079 info->stride[i] = gfc_index_one_node;
2084 static int
2085 get_rank (gfc_loopinfo *loop)
2087 int rank;
2089 rank = 0;
2090 for (; loop; loop = loop->parent)
2091 rank += loop->dimen;
2093 return rank;
2097 /* Helper routine of gfc_trans_array_constructor to determine if the
2098 bounds of the loop specified by LOOP are constant and simple enough
2099 to use with trans_constant_array_constructor. Returns the
2100 iteration count of the loop if suitable, and NULL_TREE otherwise. */
2102 static tree
2103 constant_array_constructor_loop_size (gfc_loopinfo * l)
2105 gfc_loopinfo *loop;
2106 tree size = gfc_index_one_node;
2107 tree tmp;
2108 int i, total_dim;
2110 total_dim = get_rank (l);
2112 for (loop = l; loop; loop = loop->parent)
2114 for (i = 0; i < loop->dimen; i++)
2116 /* If the bounds aren't constant, return NULL_TREE. */
2117 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2118 return NULL_TREE;
2119 if (!integer_zerop (loop->from[i]))
2121 /* Only allow nonzero "from" in one-dimensional arrays. */
2122 if (total_dim != 1)
2123 return NULL_TREE;
2124 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2125 gfc_array_index_type,
2126 loop->to[i], loop->from[i]);
2128 else
2129 tmp = loop->to[i];
2130 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2131 gfc_array_index_type, tmp, gfc_index_one_node);
2132 size = fold_build2_loc (input_location, MULT_EXPR,
2133 gfc_array_index_type, size, tmp);
2137 return size;
2141 static tree *
2142 get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2144 gfc_ss *ss;
2145 int n;
2147 gcc_assert (array->nested_ss == NULL);
2149 for (ss = array; ss; ss = ss->parent)
2150 for (n = 0; n < ss->loop->dimen; n++)
2151 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2152 return &(ss->loop->to[n]);
2154 gcc_unreachable ();
2158 static gfc_loopinfo *
2159 outermost_loop (gfc_loopinfo * loop)
2161 while (loop->parent != NULL)
2162 loop = loop->parent;
2164 return loop;
2168 /* Array constructors are handled by constructing a temporary, then using that
2169 within the scalarization loop. This is not optimal, but seems by far the
2170 simplest method. */
2172 static void
2173 trans_array_constructor (gfc_ss * ss, locus * where)
2175 gfc_constructor_base c;
2176 tree offset;
2177 tree offsetvar;
2178 tree desc;
2179 tree type;
2180 tree tmp;
2181 tree *loop_ubound0;
2182 bool dynamic;
2183 bool old_first_len, old_typespec_chararray_ctor;
2184 tree old_first_len_val;
2185 gfc_loopinfo *loop, *outer_loop;
2186 gfc_ss_info *ss_info;
2187 gfc_expr *expr;
2188 gfc_ss *s;
2190 /* Save the old values for nested checking. */
2191 old_first_len = first_len;
2192 old_first_len_val = first_len_val;
2193 old_typespec_chararray_ctor = typespec_chararray_ctor;
2195 loop = ss->loop;
2196 outer_loop = outermost_loop (loop);
2197 ss_info = ss->info;
2198 expr = ss_info->expr;
2200 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2201 typespec was given for the array constructor. */
2202 typespec_chararray_ctor = (expr->ts.u.cl
2203 && expr->ts.u.cl->length_from_typespec);
2205 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2206 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2208 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2209 first_len = true;
2212 gcc_assert (ss->dimen == ss->loop->dimen);
2214 c = expr->value.constructor;
2215 if (expr->ts.type == BT_CHARACTER)
2217 bool const_string;
2219 /* get_array_ctor_strlen walks the elements of the constructor, if a
2220 typespec was given, we already know the string length and want the one
2221 specified there. */
2222 if (typespec_chararray_ctor && expr->ts.u.cl->length
2223 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2225 gfc_se length_se;
2227 const_string = false;
2228 gfc_init_se (&length_se, NULL);
2229 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2230 gfc_charlen_type_node);
2231 ss_info->string_length = length_se.expr;
2232 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2233 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2235 else
2236 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2237 &ss_info->string_length);
2239 /* Complex character array constructors should have been taken care of
2240 and not end up here. */
2241 gcc_assert (ss_info->string_length);
2243 expr->ts.u.cl->backend_decl = ss_info->string_length;
2245 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2246 if (const_string)
2247 type = build_pointer_type (type);
2249 else
2250 type = gfc_typenode_for_spec (&expr->ts);
2252 /* See if the constructor determines the loop bounds. */
2253 dynamic = false;
2255 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2257 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
2259 /* We have a multidimensional parameter. */
2260 for (s = ss; s; s = s->parent)
2262 int n;
2263 for (n = 0; n < s->loop->dimen; n++)
2265 s->loop->from[n] = gfc_index_zero_node;
2266 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2267 gfc_index_integer_kind);
2268 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2269 gfc_array_index_type,
2270 s->loop->to[n],
2271 gfc_index_one_node);
2276 if (*loop_ubound0 == NULL_TREE)
2278 mpz_t size;
2280 /* We should have a 1-dimensional, zero-based loop. */
2281 gcc_assert (loop->parent == NULL && loop->nested == NULL);
2282 gcc_assert (loop->dimen == 1);
2283 gcc_assert (integer_zerop (loop->from[0]));
2285 /* Split the constructor size into a static part and a dynamic part.
2286 Allocate the static size up-front and record whether the dynamic
2287 size might be nonzero. */
2288 mpz_init (size);
2289 dynamic = gfc_get_array_constructor_size (&size, c);
2290 mpz_sub_ui (size, size, 1);
2291 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2292 mpz_clear (size);
2295 /* Special case constant array constructors. */
2296 if (!dynamic)
2298 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2299 if (nelem > 0)
2301 tree size = constant_array_constructor_loop_size (loop);
2302 if (size && compare_tree_int (size, nelem) == 0)
2304 trans_constant_array_constructor (ss, type);
2305 goto finish;
2310 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2311 NULL_TREE, dynamic, true, false, where);
2313 desc = ss_info->data.array.descriptor;
2314 offset = gfc_index_zero_node;
2315 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2316 TREE_NO_WARNING (offsetvar) = 1;
2317 TREE_USED (offsetvar) = 0;
2318 gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
2319 &offset, &offsetvar, dynamic);
2321 /* If the array grows dynamically, the upper bound of the loop variable
2322 is determined by the array's final upper bound. */
2323 if (dynamic)
2325 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2326 gfc_array_index_type,
2327 offsetvar, gfc_index_one_node);
2328 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2329 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2330 if (*loop_ubound0 && TREE_CODE (*loop_ubound0) == VAR_DECL)
2331 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
2332 else
2333 *loop_ubound0 = tmp;
2336 if (TREE_USED (offsetvar))
2337 pushdecl (offsetvar);
2338 else
2339 gcc_assert (INTEGER_CST_P (offset));
2341 #if 0
2342 /* Disable bound checking for now because it's probably broken. */
2343 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2345 gcc_unreachable ();
2347 #endif
2349 finish:
2350 /* Restore old values of globals. */
2351 first_len = old_first_len;
2352 first_len_val = old_first_len_val;
2353 typespec_chararray_ctor = old_typespec_chararray_ctor;
2357 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2358 called after evaluating all of INFO's vector dimensions. Go through
2359 each such vector dimension and see if we can now fill in any missing
2360 loop bounds. */
2362 static void
2363 set_vector_loop_bounds (gfc_ss * ss)
2365 gfc_loopinfo *loop, *outer_loop;
2366 gfc_array_info *info;
2367 gfc_se se;
2368 tree tmp;
2369 tree desc;
2370 tree zero;
2371 int n;
2372 int dim;
2374 outer_loop = outermost_loop (ss->loop);
2376 info = &ss->info->data.array;
2378 for (; ss; ss = ss->parent)
2380 loop = ss->loop;
2382 for (n = 0; n < loop->dimen; n++)
2384 dim = ss->dim[n];
2385 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2386 || loop->to[n] != NULL)
2387 continue;
2389 /* Loop variable N indexes vector dimension DIM, and we don't
2390 yet know the upper bound of loop variable N. Set it to the
2391 difference between the vector's upper and lower bounds. */
2392 gcc_assert (loop->from[n] == gfc_index_zero_node);
2393 gcc_assert (info->subscript[dim]
2394 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2396 gfc_init_se (&se, NULL);
2397 desc = info->subscript[dim]->info->data.array.descriptor;
2398 zero = gfc_rank_cst[0];
2399 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2400 gfc_array_index_type,
2401 gfc_conv_descriptor_ubound_get (desc, zero),
2402 gfc_conv_descriptor_lbound_get (desc, zero));
2403 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2404 loop->to[n] = tmp;
2410 /* Add the pre and post chains for all the scalar expressions in a SS chain
2411 to loop. This is called after the loop parameters have been calculated,
2412 but before the actual scalarizing loops. */
2414 static void
2415 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2416 locus * where)
2418 gfc_loopinfo *nested_loop, *outer_loop;
2419 gfc_se se;
2420 gfc_ss_info *ss_info;
2421 gfc_array_info *info;
2422 gfc_expr *expr;
2423 int n;
2425 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
2426 arguments could get evaluated multiple times. */
2427 if (ss->is_alloc_lhs)
2428 return;
2430 outer_loop = outermost_loop (loop);
2432 /* TODO: This can generate bad code if there are ordering dependencies,
2433 e.g., a callee allocated function and an unknown size constructor. */
2434 gcc_assert (ss != NULL);
2436 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2438 gcc_assert (ss);
2440 /* Cross loop arrays are handled from within the most nested loop. */
2441 if (ss->nested_ss != NULL)
2442 continue;
2444 ss_info = ss->info;
2445 expr = ss_info->expr;
2446 info = &ss_info->data.array;
2448 switch (ss_info->type)
2450 case GFC_SS_SCALAR:
2451 /* Scalar expression. Evaluate this now. This includes elemental
2452 dimension indices, but not array section bounds. */
2453 gfc_init_se (&se, NULL);
2454 gfc_conv_expr (&se, expr);
2455 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2457 if (expr->ts.type != BT_CHARACTER)
2459 /* Move the evaluation of scalar expressions outside the
2460 scalarization loop, except for WHERE assignments. */
2461 if (subscript)
2462 se.expr = convert(gfc_array_index_type, se.expr);
2463 if (!ss_info->where)
2464 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
2465 gfc_add_block_to_block (&outer_loop->pre, &se.post);
2467 else
2468 gfc_add_block_to_block (&outer_loop->post, &se.post);
2470 ss_info->data.scalar.value = se.expr;
2471 ss_info->string_length = se.string_length;
2472 break;
2474 case GFC_SS_REFERENCE:
2475 /* Scalar argument to elemental procedure. */
2476 gfc_init_se (&se, NULL);
2477 if (ss_info->can_be_null_ref)
2479 /* If the actual argument can be absent (in other words, it can
2480 be a NULL reference), don't try to evaluate it; pass instead
2481 the reference directly. */
2482 gfc_conv_expr_reference (&se, expr);
2484 else
2486 /* Otherwise, evaluate the argument outside the loop and pass
2487 a reference to the value. */
2488 gfc_conv_expr (&se, expr);
2490 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2491 gfc_add_block_to_block (&outer_loop->post, &se.post);
2492 if (gfc_is_class_scalar_expr (expr))
2493 /* This is necessary because the dynamic type will always be
2494 large than the declared type. In consequence, assigning
2495 the value to a temporary could segfault.
2496 OOP-TODO: see if this is generally correct or is the value
2497 has to be written to an allocated temporary, whose address
2498 is passed via ss_info. */
2499 ss_info->data.scalar.value = se.expr;
2500 else
2501 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
2502 &outer_loop->pre);
2504 ss_info->string_length = se.string_length;
2505 break;
2507 case GFC_SS_SECTION:
2508 /* Add the expressions for scalar and vector subscripts. */
2509 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2510 if (info->subscript[n])
2511 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2513 set_vector_loop_bounds (ss);
2514 break;
2516 case GFC_SS_VECTOR:
2517 /* Get the vector's descriptor and store it in SS. */
2518 gfc_init_se (&se, NULL);
2519 gfc_conv_expr_descriptor (&se, expr);
2520 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2521 gfc_add_block_to_block (&outer_loop->post, &se.post);
2522 info->descriptor = se.expr;
2523 break;
2525 case GFC_SS_INTRINSIC:
2526 gfc_add_intrinsic_ss_code (loop, ss);
2527 break;
2529 case GFC_SS_FUNCTION:
2530 /* Array function return value. We call the function and save its
2531 result in a temporary for use inside the loop. */
2532 gfc_init_se (&se, NULL);
2533 se.loop = loop;
2534 se.ss = ss;
2535 gfc_conv_expr (&se, expr);
2536 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2537 gfc_add_block_to_block (&outer_loop->post, &se.post);
2538 ss_info->string_length = se.string_length;
2539 break;
2541 case GFC_SS_CONSTRUCTOR:
2542 if (expr->ts.type == BT_CHARACTER
2543 && ss_info->string_length == NULL
2544 && expr->ts.u.cl
2545 && expr->ts.u.cl->length)
2547 gfc_init_se (&se, NULL);
2548 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2549 gfc_charlen_type_node);
2550 ss_info->string_length = se.expr;
2551 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2552 gfc_add_block_to_block (&outer_loop->post, &se.post);
2554 trans_array_constructor (ss, where);
2555 break;
2557 case GFC_SS_TEMP:
2558 case GFC_SS_COMPONENT:
2559 /* Do nothing. These are handled elsewhere. */
2560 break;
2562 default:
2563 gcc_unreachable ();
2567 if (!subscript)
2568 for (nested_loop = loop->nested; nested_loop;
2569 nested_loop = nested_loop->next)
2570 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
2574 /* Translate expressions for the descriptor and data pointer of a SS. */
2575 /*GCC ARRAYS*/
2577 static void
2578 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2580 gfc_se se;
2581 gfc_ss_info *ss_info;
2582 gfc_array_info *info;
2583 tree tmp;
2585 ss_info = ss->info;
2586 info = &ss_info->data.array;
2588 /* Get the descriptor for the array to be scalarized. */
2589 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2590 gfc_init_se (&se, NULL);
2591 se.descriptor_only = 1;
2592 gfc_conv_expr_lhs (&se, ss_info->expr);
2593 gfc_add_block_to_block (block, &se.pre);
2594 info->descriptor = se.expr;
2595 ss_info->string_length = se.string_length;
2597 if (base)
2599 /* Also the data pointer. */
2600 tmp = gfc_conv_array_data (se.expr);
2601 /* If this is a variable or address of a variable we use it directly.
2602 Otherwise we must evaluate it now to avoid breaking dependency
2603 analysis by pulling the expressions for elemental array indices
2604 inside the loop. */
2605 if (!(DECL_P (tmp)
2606 || (TREE_CODE (tmp) == ADDR_EXPR
2607 && DECL_P (TREE_OPERAND (tmp, 0)))))
2608 tmp = gfc_evaluate_now (tmp, block);
2609 info->data = tmp;
2611 tmp = gfc_conv_array_offset (se.expr);
2612 info->offset = gfc_evaluate_now (tmp, block);
2614 /* Make absolutely sure that the saved_offset is indeed saved
2615 so that the variable is still accessible after the loops
2616 are translated. */
2617 info->saved_offset = info->offset;
2622 /* Initialize a gfc_loopinfo structure. */
2624 void
2625 gfc_init_loopinfo (gfc_loopinfo * loop)
2627 int n;
2629 memset (loop, 0, sizeof (gfc_loopinfo));
2630 gfc_init_block (&loop->pre);
2631 gfc_init_block (&loop->post);
2633 /* Initially scalarize in order and default to no loop reversal. */
2634 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2636 loop->order[n] = n;
2637 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2640 loop->ss = gfc_ss_terminator;
2644 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2645 chain. */
2647 void
2648 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2650 se->loop = loop;
2654 /* Return an expression for the data pointer of an array. */
2656 tree
2657 gfc_conv_array_data (tree descriptor)
2659 tree type;
2661 type = TREE_TYPE (descriptor);
2662 if (GFC_ARRAY_TYPE_P (type))
2664 if (TREE_CODE (type) == POINTER_TYPE)
2665 return descriptor;
2666 else
2668 /* Descriptorless arrays. */
2669 return gfc_build_addr_expr (NULL_TREE, descriptor);
2672 else
2673 return gfc_conv_descriptor_data_get (descriptor);
2677 /* Return an expression for the base offset of an array. */
2679 tree
2680 gfc_conv_array_offset (tree descriptor)
2682 tree type;
2684 type = TREE_TYPE (descriptor);
2685 if (GFC_ARRAY_TYPE_P (type))
2686 return GFC_TYPE_ARRAY_OFFSET (type);
2687 else
2688 return gfc_conv_descriptor_offset_get (descriptor);
2692 /* Get an expression for the array stride. */
2694 tree
2695 gfc_conv_array_stride (tree descriptor, int dim)
2697 tree tmp;
2698 tree type;
2700 type = TREE_TYPE (descriptor);
2702 /* For descriptorless arrays use the array size. */
2703 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2704 if (tmp != NULL_TREE)
2705 return tmp;
2707 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2708 return tmp;
2712 /* Like gfc_conv_array_stride, but for the lower bound. */
2714 tree
2715 gfc_conv_array_lbound (tree descriptor, int dim)
2717 tree tmp;
2718 tree type;
2720 type = TREE_TYPE (descriptor);
2722 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2723 if (tmp != NULL_TREE)
2724 return tmp;
2726 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2727 return tmp;
2731 /* Like gfc_conv_array_stride, but for the upper bound. */
2733 tree
2734 gfc_conv_array_ubound (tree descriptor, int dim)
2736 tree tmp;
2737 tree type;
2739 type = TREE_TYPE (descriptor);
2741 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2742 if (tmp != NULL_TREE)
2743 return tmp;
2745 /* This should only ever happen when passing an assumed shape array
2746 as an actual parameter. The value will never be used. */
2747 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2748 return gfc_index_zero_node;
2750 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2751 return tmp;
2755 /* Generate code to perform an array index bound check. */
2757 static tree
2758 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
2759 locus * where, bool check_upper)
2761 tree fault;
2762 tree tmp_lo, tmp_up;
2763 tree descriptor;
2764 char *msg;
2765 const char * name = NULL;
2767 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2768 return index;
2770 descriptor = ss->info->data.array.descriptor;
2772 index = gfc_evaluate_now (index, &se->pre);
2774 /* We find a name for the error message. */
2775 name = ss->info->expr->symtree->n.sym->name;
2776 gcc_assert (name != NULL);
2778 if (TREE_CODE (descriptor) == VAR_DECL)
2779 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
2781 /* If upper bound is present, include both bounds in the error message. */
2782 if (check_upper)
2784 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2785 tmp_up = gfc_conv_array_ubound (descriptor, n);
2787 if (name)
2788 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2789 "outside of expected range (%%ld:%%ld)", n+1, name);
2790 else
2791 asprintf (&msg, "Index '%%ld' of dimension %d "
2792 "outside of expected range (%%ld:%%ld)", n+1);
2794 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2795 index, tmp_lo);
2796 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2797 fold_convert (long_integer_type_node, index),
2798 fold_convert (long_integer_type_node, tmp_lo),
2799 fold_convert (long_integer_type_node, tmp_up));
2800 fault = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2801 index, tmp_up);
2802 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2803 fold_convert (long_integer_type_node, index),
2804 fold_convert (long_integer_type_node, tmp_lo),
2805 fold_convert (long_integer_type_node, tmp_up));
2806 free (msg);
2808 else
2810 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2812 if (name)
2813 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2814 "below lower bound of %%ld", n+1, name);
2815 else
2816 asprintf (&msg, "Index '%%ld' of dimension %d "
2817 "below lower bound of %%ld", n+1);
2819 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2820 index, tmp_lo);
2821 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2822 fold_convert (long_integer_type_node, index),
2823 fold_convert (long_integer_type_node, tmp_lo));
2824 free (msg);
2827 return index;
2831 /* Return the offset for an index. Performs bound checking for elemental
2832 dimensions. Single element references are processed separately.
2833 DIM is the array dimension, I is the loop dimension. */
2835 static tree
2836 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
2837 gfc_array_ref * ar, tree stride)
2839 gfc_array_info *info;
2840 tree index;
2841 tree desc;
2842 tree data;
2844 info = &ss->info->data.array;
2846 /* Get the index into the array for this dimension. */
2847 if (ar)
2849 gcc_assert (ar->type != AR_ELEMENT);
2850 switch (ar->dimen_type[dim])
2852 case DIMEN_THIS_IMAGE:
2853 gcc_unreachable ();
2854 break;
2855 case DIMEN_ELEMENT:
2856 /* Elemental dimension. */
2857 gcc_assert (info->subscript[dim]
2858 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
2859 /* We've already translated this value outside the loop. */
2860 index = info->subscript[dim]->info->data.scalar.value;
2862 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2863 ar->as->type != AS_ASSUMED_SIZE
2864 || dim < ar->dimen - 1);
2865 break;
2867 case DIMEN_VECTOR:
2868 gcc_assert (info && se->loop);
2869 gcc_assert (info->subscript[dim]
2870 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2871 desc = info->subscript[dim]->info->data.array.descriptor;
2873 /* Get a zero-based index into the vector. */
2874 index = fold_build2_loc (input_location, MINUS_EXPR,
2875 gfc_array_index_type,
2876 se->loop->loopvar[i], se->loop->from[i]);
2878 /* Multiply the index by the stride. */
2879 index = fold_build2_loc (input_location, MULT_EXPR,
2880 gfc_array_index_type,
2881 index, gfc_conv_array_stride (desc, 0));
2883 /* Read the vector to get an index into info->descriptor. */
2884 data = build_fold_indirect_ref_loc (input_location,
2885 gfc_conv_array_data (desc));
2886 index = gfc_build_array_ref (data, index, NULL);
2887 index = gfc_evaluate_now (index, &se->pre);
2888 index = fold_convert (gfc_array_index_type, index);
2890 /* Do any bounds checking on the final info->descriptor index. */
2891 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2892 ar->as->type != AS_ASSUMED_SIZE
2893 || dim < ar->dimen - 1);
2894 break;
2896 case DIMEN_RANGE:
2897 /* Scalarized dimension. */
2898 gcc_assert (info && se->loop);
2900 /* Multiply the loop variable by the stride and delta. */
2901 index = se->loop->loopvar[i];
2902 if (!integer_onep (info->stride[dim]))
2903 index = fold_build2_loc (input_location, MULT_EXPR,
2904 gfc_array_index_type, index,
2905 info->stride[dim]);
2906 if (!integer_zerop (info->delta[dim]))
2907 index = fold_build2_loc (input_location, PLUS_EXPR,
2908 gfc_array_index_type, index,
2909 info->delta[dim]);
2910 break;
2912 default:
2913 gcc_unreachable ();
2916 else
2918 /* Temporary array or derived type component. */
2919 gcc_assert (se->loop);
2920 index = se->loop->loopvar[se->loop->order[i]];
2922 /* Pointer functions can have stride[0] different from unity.
2923 Use the stride returned by the function call and stored in
2924 the descriptor for the temporary. */
2925 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
2926 && se->ss->info->expr
2927 && se->ss->info->expr->symtree
2928 && se->ss->info->expr->symtree->n.sym->result
2929 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
2930 stride = gfc_conv_descriptor_stride_get (info->descriptor,
2931 gfc_rank_cst[dim]);
2933 if (!integer_zerop (info->delta[dim]))
2934 index = fold_build2_loc (input_location, PLUS_EXPR,
2935 gfc_array_index_type, index, info->delta[dim]);
2938 /* Multiply by the stride. */
2939 if (!integer_onep (stride))
2940 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2941 index, stride);
2943 return index;
2947 /* Build a scalarized array reference using the vptr 'size'. */
2949 static bool
2950 build_class_array_ref (gfc_se *se, tree base, tree index)
2952 tree type;
2953 tree size;
2954 tree offset;
2955 tree decl;
2956 tree tmp;
2957 gfc_expr *expr = se->ss->info->expr;
2958 gfc_ref *ref;
2959 gfc_ref *class_ref;
2960 gfc_typespec *ts;
2962 if (expr == NULL || expr->ts.type != BT_CLASS)
2963 return false;
2965 if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS)
2966 ts = &expr->symtree->n.sym->ts;
2967 else
2968 ts = NULL;
2969 class_ref = NULL;
2971 for (ref = expr->ref; ref; ref = ref->next)
2973 if (ref->type == REF_COMPONENT
2974 && ref->u.c.component->ts.type == BT_CLASS
2975 && ref->next && ref->next->type == REF_COMPONENT
2976 && strcmp (ref->next->u.c.component->name, "_data") == 0
2977 && ref->next->next
2978 && ref->next->next->type == REF_ARRAY
2979 && ref->next->next->u.ar.type != AR_ELEMENT)
2981 ts = &ref->u.c.component->ts;
2982 class_ref = ref;
2983 break;
2987 if (ts == NULL)
2988 return false;
2990 if (class_ref == NULL)
2991 decl = expr->symtree->n.sym->backend_decl;
2992 else
2994 /* Remove everything after the last class reference, convert the
2995 expression and then recover its tailend once more. */
2996 gfc_se tmpse;
2997 ref = class_ref->next;
2998 class_ref->next = NULL;
2999 gfc_init_se (&tmpse, NULL);
3000 gfc_conv_expr (&tmpse, expr);
3001 decl = tmpse.expr;
3002 class_ref->next = ref;
3005 size = gfc_vtable_size_get (decl);
3007 /* Build the address of the element. */
3008 type = TREE_TYPE (TREE_TYPE (base));
3009 size = fold_convert (TREE_TYPE (index), size);
3010 offset = fold_build2_loc (input_location, MULT_EXPR,
3011 gfc_array_index_type,
3012 index, size);
3013 tmp = gfc_build_addr_expr (pvoid_type_node, base);
3014 tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
3015 tmp = fold_convert (build_pointer_type (type), tmp);
3017 /* Return the element in the se expression. */
3018 se->expr = build_fold_indirect_ref_loc (input_location, tmp);
3019 return true;
3023 /* Build a scalarized reference to an array. */
3025 static void
3026 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
3028 gfc_array_info *info;
3029 tree decl = NULL_TREE;
3030 tree index;
3031 tree tmp;
3032 gfc_ss *ss;
3033 gfc_expr *expr;
3034 int n;
3036 ss = se->ss;
3037 expr = ss->info->expr;
3038 info = &ss->info->data.array;
3039 if (ar)
3040 n = se->loop->order[0];
3041 else
3042 n = 0;
3044 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
3045 /* Add the offset for this dimension to the stored offset for all other
3046 dimensions. */
3047 if (!integer_zerop (info->offset))
3048 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3049 index, info->offset);
3051 if (expr && is_subref_array (expr))
3052 decl = expr->symtree->n.sym->backend_decl;
3054 tmp = build_fold_indirect_ref_loc (input_location, info->data);
3056 /* Use the vptr 'size' field to access a class the element of a class
3057 array. */
3058 if (build_class_array_ref (se, tmp, index))
3059 return;
3061 se->expr = gfc_build_array_ref (tmp, index, decl);
3065 /* Translate access of temporary array. */
3067 void
3068 gfc_conv_tmp_array_ref (gfc_se * se)
3070 se->string_length = se->ss->info->string_length;
3071 gfc_conv_scalarized_array_ref (se, NULL);
3072 gfc_advance_se_ss_chain (se);
3075 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3077 static void
3078 add_to_offset (tree *cst_offset, tree *offset, tree t)
3080 if (TREE_CODE (t) == INTEGER_CST)
3081 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3082 else
3084 if (!integer_zerop (*offset))
3085 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3086 gfc_array_index_type, *offset, t);
3087 else
3088 *offset = t;
3093 static tree
3094 build_array_ref (tree desc, tree offset, tree decl)
3096 tree tmp;
3097 tree type;
3099 /* Class container types do not always have the GFC_CLASS_TYPE_P
3100 but the canonical type does. */
3101 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
3102 && TREE_CODE (desc) == COMPONENT_REF)
3104 type = TREE_TYPE (TREE_OPERAND (desc, 0));
3105 if (TYPE_CANONICAL (type)
3106 && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
3107 type = TYPE_CANONICAL (type);
3109 else
3110 type = NULL;
3112 /* Class array references need special treatment because the assigned
3113 type size needs to be used to point to the element. */
3114 if (type && GFC_CLASS_TYPE_P (type))
3116 type = gfc_get_element_type (TREE_TYPE (desc));
3117 tmp = TREE_OPERAND (desc, 0);
3118 tmp = gfc_get_class_array_ref (offset, tmp);
3119 tmp = fold_convert (build_pointer_type (type), tmp);
3120 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3121 return tmp;
3124 tmp = gfc_conv_array_data (desc);
3125 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3126 tmp = gfc_build_array_ref (tmp, offset, decl);
3127 return tmp;
3131 /* Build an array reference. se->expr already holds the array descriptor.
3132 This should be either a variable, indirect variable reference or component
3133 reference. For arrays which do not have a descriptor, se->expr will be
3134 the data pointer.
3135 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3137 void
3138 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
3139 locus * where)
3141 int n;
3142 tree offset, cst_offset;
3143 tree tmp;
3144 tree stride;
3145 gfc_se indexse;
3146 gfc_se tmpse;
3148 if (ar->dimen == 0)
3150 gcc_assert (ar->codimen);
3152 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3153 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
3154 else
3156 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
3157 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
3158 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
3160 /* Use the actual tree type and not the wrapped coarray. */
3161 if (!se->want_pointer)
3162 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
3163 se->expr);
3166 return;
3169 /* Handle scalarized references separately. */
3170 if (ar->type != AR_ELEMENT)
3172 gfc_conv_scalarized_array_ref (se, ar);
3173 gfc_advance_se_ss_chain (se);
3174 return;
3177 cst_offset = offset = gfc_index_zero_node;
3178 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
3180 /* Calculate the offsets from all the dimensions. Make sure to associate
3181 the final offset so that we form a chain of loop invariant summands. */
3182 for (n = ar->dimen - 1; n >= 0; n--)
3184 /* Calculate the index for this dimension. */
3185 gfc_init_se (&indexse, se);
3186 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
3187 gfc_add_block_to_block (&se->pre, &indexse.pre);
3189 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3191 /* Check array bounds. */
3192 tree cond;
3193 char *msg;
3195 /* Evaluate the indexse.expr only once. */
3196 indexse.expr = save_expr (indexse.expr);
3198 /* Lower bound. */
3199 tmp = gfc_conv_array_lbound (se->expr, n);
3200 if (sym->attr.temporary)
3202 gfc_init_se (&tmpse, se);
3203 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
3204 gfc_array_index_type);
3205 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3206 tmp = tmpse.expr;
3209 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
3210 indexse.expr, tmp);
3211 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3212 "below lower bound of %%ld", n+1, sym->name);
3213 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3214 fold_convert (long_integer_type_node,
3215 indexse.expr),
3216 fold_convert (long_integer_type_node, tmp));
3217 free (msg);
3219 /* Upper bound, but not for the last dimension of assumed-size
3220 arrays. */
3221 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
3223 tmp = gfc_conv_array_ubound (se->expr, n);
3224 if (sym->attr.temporary)
3226 gfc_init_se (&tmpse, se);
3227 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
3228 gfc_array_index_type);
3229 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3230 tmp = tmpse.expr;
3233 cond = fold_build2_loc (input_location, GT_EXPR,
3234 boolean_type_node, indexse.expr, tmp);
3235 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3236 "above upper bound of %%ld", n+1, sym->name);
3237 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3238 fold_convert (long_integer_type_node,
3239 indexse.expr),
3240 fold_convert (long_integer_type_node, tmp));
3241 free (msg);
3245 /* Multiply the index by the stride. */
3246 stride = gfc_conv_array_stride (se->expr, n);
3247 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3248 indexse.expr, stride);
3250 /* And add it to the total. */
3251 add_to_offset (&cst_offset, &offset, tmp);
3254 if (!integer_zerop (cst_offset))
3255 offset = fold_build2_loc (input_location, PLUS_EXPR,
3256 gfc_array_index_type, offset, cst_offset);
3258 se->expr = build_array_ref (se->expr, offset, sym->backend_decl);
3262 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
3263 LOOP_DIM dimension (if any) to array's offset. */
3265 static void
3266 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
3267 gfc_array_ref *ar, int array_dim, int loop_dim)
3269 gfc_se se;
3270 gfc_array_info *info;
3271 tree stride, index;
3273 info = &ss->info->data.array;
3275 gfc_init_se (&se, NULL);
3276 se.loop = loop;
3277 se.expr = info->descriptor;
3278 stride = gfc_conv_array_stride (info->descriptor, array_dim);
3279 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
3280 gfc_add_block_to_block (pblock, &se.pre);
3282 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
3283 gfc_array_index_type,
3284 info->offset, index);
3285 info->offset = gfc_evaluate_now (info->offset, pblock);
3289 /* Generate the code to be executed immediately before entering a
3290 scalarization loop. */
3292 static void
3293 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
3294 stmtblock_t * pblock)
3296 tree stride;
3297 gfc_ss_info *ss_info;
3298 gfc_array_info *info;
3299 gfc_ss_type ss_type;
3300 gfc_ss *ss, *pss;
3301 gfc_loopinfo *ploop;
3302 gfc_array_ref *ar;
3303 int i;
3305 /* This code will be executed before entering the scalarization loop
3306 for this dimension. */
3307 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3309 ss_info = ss->info;
3311 if ((ss_info->useflags & flag) == 0)
3312 continue;
3314 ss_type = ss_info->type;
3315 if (ss_type != GFC_SS_SECTION
3316 && ss_type != GFC_SS_FUNCTION
3317 && ss_type != GFC_SS_CONSTRUCTOR
3318 && ss_type != GFC_SS_COMPONENT)
3319 continue;
3321 info = &ss_info->data.array;
3323 gcc_assert (dim < ss->dimen);
3324 gcc_assert (ss->dimen == loop->dimen);
3326 if (info->ref)
3327 ar = &info->ref->u.ar;
3328 else
3329 ar = NULL;
3331 if (dim == loop->dimen - 1 && loop->parent != NULL)
3333 /* If we are in the outermost dimension of this loop, the previous
3334 dimension shall be in the parent loop. */
3335 gcc_assert (ss->parent != NULL);
3337 pss = ss->parent;
3338 ploop = loop->parent;
3340 /* ss and ss->parent are about the same array. */
3341 gcc_assert (ss_info == pss->info);
3343 else
3345 ploop = loop;
3346 pss = ss;
3349 if (dim == loop->dimen - 1)
3350 i = 0;
3351 else
3352 i = dim + 1;
3354 /* For the time being, there is no loop reordering. */
3355 gcc_assert (i == ploop->order[i]);
3356 i = ploop->order[i];
3358 if (dim == loop->dimen - 1 && loop->parent == NULL)
3360 stride = gfc_conv_array_stride (info->descriptor,
3361 innermost_ss (ss)->dim[i]);
3363 /* Calculate the stride of the innermost loop. Hopefully this will
3364 allow the backend optimizers to do their stuff more effectively.
3366 info->stride0 = gfc_evaluate_now (stride, pblock);
3368 /* For the outermost loop calculate the offset due to any
3369 elemental dimensions. It will have been initialized with the
3370 base offset of the array. */
3371 if (info->ref)
3373 for (i = 0; i < ar->dimen; i++)
3375 if (ar->dimen_type[i] != DIMEN_ELEMENT)
3376 continue;
3378 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
3382 else
3383 /* Add the offset for the previous loop dimension. */
3384 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
3386 /* Remember this offset for the second loop. */
3387 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
3388 info->saved_offset = info->offset;
3393 /* Start a scalarized expression. Creates a scope and declares loop
3394 variables. */
3396 void
3397 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
3399 int dim;
3400 int n;
3401 int flags;
3403 gcc_assert (!loop->array_parameter);
3405 for (dim = loop->dimen - 1; dim >= 0; dim--)
3407 n = loop->order[dim];
3409 gfc_start_block (&loop->code[n]);
3411 /* Create the loop variable. */
3412 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
3414 if (dim < loop->temp_dim)
3415 flags = 3;
3416 else
3417 flags = 1;
3418 /* Calculate values that will be constant within this loop. */
3419 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3421 gfc_start_block (pbody);
3425 /* Generates the actual loop code for a scalarization loop. */
3427 void
3428 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3429 stmtblock_t * pbody)
3431 stmtblock_t block;
3432 tree cond;
3433 tree tmp;
3434 tree loopbody;
3435 tree exit_label;
3436 tree stmt;
3437 tree init;
3438 tree incr;
3440 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
3441 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3442 && n == loop->dimen - 1)
3444 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3445 init = make_tree_vec (1);
3446 cond = make_tree_vec (1);
3447 incr = make_tree_vec (1);
3449 /* Cycle statement is implemented with a goto. Exit statement must not
3450 be present for this loop. */
3451 exit_label = gfc_build_label_decl (NULL_TREE);
3452 TREE_USED (exit_label) = 1;
3454 /* Label for cycle statements (if needed). */
3455 tmp = build1_v (LABEL_EXPR, exit_label);
3456 gfc_add_expr_to_block (pbody, tmp);
3458 stmt = make_node (OMP_FOR);
3460 TREE_TYPE (stmt) = void_type_node;
3461 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3463 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3464 OMP_CLAUSE_SCHEDULE);
3465 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3466 = OMP_CLAUSE_SCHEDULE_STATIC;
3467 if (ompws_flags & OMPWS_NOWAIT)
3468 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3469 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3471 /* Initialize the loopvar. */
3472 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3473 loop->from[n]);
3474 OMP_FOR_INIT (stmt) = init;
3475 /* The exit condition. */
3476 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3477 boolean_type_node,
3478 loop->loopvar[n], loop->to[n]);
3479 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3480 OMP_FOR_COND (stmt) = cond;
3481 /* Increment the loopvar. */
3482 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3483 loop->loopvar[n], gfc_index_one_node);
3484 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3485 void_type_node, loop->loopvar[n], tmp);
3486 OMP_FOR_INCR (stmt) = incr;
3488 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3489 gfc_add_expr_to_block (&loop->code[n], stmt);
3491 else
3493 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3494 && (loop->temp_ss == NULL);
3496 loopbody = gfc_finish_block (pbody);
3498 if (reverse_loop)
3500 tmp = loop->from[n];
3501 loop->from[n] = loop->to[n];
3502 loop->to[n] = tmp;
3505 /* Initialize the loopvar. */
3506 if (loop->loopvar[n] != loop->from[n])
3507 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3509 exit_label = gfc_build_label_decl (NULL_TREE);
3511 /* Generate the loop body. */
3512 gfc_init_block (&block);
3514 /* The exit condition. */
3515 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3516 boolean_type_node, loop->loopvar[n], loop->to[n]);
3517 tmp = build1_v (GOTO_EXPR, exit_label);
3518 TREE_USED (exit_label) = 1;
3519 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3520 gfc_add_expr_to_block (&block, tmp);
3522 /* The main body. */
3523 gfc_add_expr_to_block (&block, loopbody);
3525 /* Increment the loopvar. */
3526 tmp = fold_build2_loc (input_location,
3527 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3528 gfc_array_index_type, loop->loopvar[n],
3529 gfc_index_one_node);
3531 gfc_add_modify (&block, loop->loopvar[n], tmp);
3533 /* Build the loop. */
3534 tmp = gfc_finish_block (&block);
3535 tmp = build1_v (LOOP_EXPR, tmp);
3536 gfc_add_expr_to_block (&loop->code[n], tmp);
3538 /* Add the exit label. */
3539 tmp = build1_v (LABEL_EXPR, exit_label);
3540 gfc_add_expr_to_block (&loop->code[n], tmp);
3546 /* Finishes and generates the loops for a scalarized expression. */
3548 void
3549 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3551 int dim;
3552 int n;
3553 gfc_ss *ss;
3554 stmtblock_t *pblock;
3555 tree tmp;
3557 pblock = body;
3558 /* Generate the loops. */
3559 for (dim = 0; dim < loop->dimen; dim++)
3561 n = loop->order[dim];
3562 gfc_trans_scalarized_loop_end (loop, n, pblock);
3563 loop->loopvar[n] = NULL_TREE;
3564 pblock = &loop->code[n];
3567 tmp = gfc_finish_block (pblock);
3568 gfc_add_expr_to_block (&loop->pre, tmp);
3570 /* Clear all the used flags. */
3571 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3572 if (ss->parent == NULL)
3573 ss->info->useflags = 0;
3577 /* Finish the main body of a scalarized expression, and start the secondary
3578 copying body. */
3580 void
3581 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
3583 int dim;
3584 int n;
3585 stmtblock_t *pblock;
3586 gfc_ss *ss;
3588 pblock = body;
3589 /* We finish as many loops as are used by the temporary. */
3590 for (dim = 0; dim < loop->temp_dim - 1; dim++)
3592 n = loop->order[dim];
3593 gfc_trans_scalarized_loop_end (loop, n, pblock);
3594 loop->loopvar[n] = NULL_TREE;
3595 pblock = &loop->code[n];
3598 /* We don't want to finish the outermost loop entirely. */
3599 n = loop->order[loop->temp_dim - 1];
3600 gfc_trans_scalarized_loop_end (loop, n, pblock);
3602 /* Restore the initial offsets. */
3603 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3605 gfc_ss_type ss_type;
3606 gfc_ss_info *ss_info;
3608 ss_info = ss->info;
3610 if ((ss_info->useflags & 2) == 0)
3611 continue;
3613 ss_type = ss_info->type;
3614 if (ss_type != GFC_SS_SECTION
3615 && ss_type != GFC_SS_FUNCTION
3616 && ss_type != GFC_SS_CONSTRUCTOR
3617 && ss_type != GFC_SS_COMPONENT)
3618 continue;
3620 ss_info->data.array.offset = ss_info->data.array.saved_offset;
3623 /* Restart all the inner loops we just finished. */
3624 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
3626 n = loop->order[dim];
3628 gfc_start_block (&loop->code[n]);
3630 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
3632 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
3635 /* Start a block for the secondary copying code. */
3636 gfc_start_block (body);
3640 /* Precalculate (either lower or upper) bound of an array section.
3641 BLOCK: Block in which the (pre)calculation code will go.
3642 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
3643 VALUES[DIM]: Specified bound (NULL <=> unspecified).
3644 DESC: Array descriptor from which the bound will be picked if unspecified
3645 (either lower or upper bound according to LBOUND). */
3647 static void
3648 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
3649 tree desc, int dim, bool lbound)
3651 gfc_se se;
3652 gfc_expr * input_val = values[dim];
3653 tree *output = &bounds[dim];
3656 if (input_val)
3658 /* Specified section bound. */
3659 gfc_init_se (&se, NULL);
3660 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
3661 gfc_add_block_to_block (block, &se.pre);
3662 *output = se.expr;
3664 else
3666 /* No specific bound specified so use the bound of the array. */
3667 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
3668 gfc_conv_array_ubound (desc, dim);
3670 *output = gfc_evaluate_now (*output, block);
3674 /* Calculate the lower bound of an array section. */
3676 static void
3677 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
3679 gfc_expr *stride = NULL;
3680 tree desc;
3681 gfc_se se;
3682 gfc_array_info *info;
3683 gfc_array_ref *ar;
3685 gcc_assert (ss->info->type == GFC_SS_SECTION);
3687 info = &ss->info->data.array;
3688 ar = &info->ref->u.ar;
3690 if (ar->dimen_type[dim] == DIMEN_VECTOR)
3692 /* We use a zero-based index to access the vector. */
3693 info->start[dim] = gfc_index_zero_node;
3694 info->end[dim] = NULL;
3695 info->stride[dim] = gfc_index_one_node;
3696 return;
3699 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
3700 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
3701 desc = info->descriptor;
3702 stride = ar->stride[dim];
3704 /* Calculate the start of the range. For vector subscripts this will
3705 be the range of the vector. */
3706 evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true);
3708 /* Similarly calculate the end. Although this is not used in the
3709 scalarizer, it is needed when checking bounds and where the end
3710 is an expression with side-effects. */
3711 evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false);
3713 /* Calculate the stride. */
3714 if (stride == NULL)
3715 info->stride[dim] = gfc_index_one_node;
3716 else
3718 gfc_init_se (&se, NULL);
3719 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3720 gfc_add_block_to_block (&loop->pre, &se.pre);
3721 info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre);
3726 /* Calculates the range start and stride for a SS chain. Also gets the
3727 descriptor and data pointer. The range of vector subscripts is the size
3728 of the vector. Array bounds are also checked. */
3730 void
3731 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3733 int n;
3734 tree tmp;
3735 gfc_ss *ss;
3736 tree desc;
3738 loop->dimen = 0;
3739 /* Determine the rank of the loop. */
3740 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3742 switch (ss->info->type)
3744 case GFC_SS_SECTION:
3745 case GFC_SS_CONSTRUCTOR:
3746 case GFC_SS_FUNCTION:
3747 case GFC_SS_COMPONENT:
3748 loop->dimen = ss->dimen;
3749 goto done;
3751 /* As usual, lbound and ubound are exceptions!. */
3752 case GFC_SS_INTRINSIC:
3753 switch (ss->info->expr->value.function.isym->id)
3755 case GFC_ISYM_LBOUND:
3756 case GFC_ISYM_UBOUND:
3757 case GFC_ISYM_LCOBOUND:
3758 case GFC_ISYM_UCOBOUND:
3759 case GFC_ISYM_THIS_IMAGE:
3760 loop->dimen = ss->dimen;
3761 goto done;
3763 default:
3764 break;
3767 default:
3768 break;
3772 /* We should have determined the rank of the expression by now. If
3773 not, that's bad news. */
3774 gcc_unreachable ();
3776 done:
3777 /* Loop over all the SS in the chain. */
3778 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3780 gfc_ss_info *ss_info;
3781 gfc_array_info *info;
3782 gfc_expr *expr;
3784 ss_info = ss->info;
3785 expr = ss_info->expr;
3786 info = &ss_info->data.array;
3788 if (expr && expr->shape && !info->shape)
3789 info->shape = expr->shape;
3791 switch (ss_info->type)
3793 case GFC_SS_SECTION:
3794 /* Get the descriptor for the array. If it is a cross loops array,
3795 we got the descriptor already in the outermost loop. */
3796 if (ss->parent == NULL)
3797 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
3799 for (n = 0; n < ss->dimen; n++)
3800 gfc_conv_section_startstride (loop, ss, ss->dim[n]);
3801 break;
3803 case GFC_SS_INTRINSIC:
3804 switch (expr->value.function.isym->id)
3806 /* Fall through to supply start and stride. */
3807 case GFC_ISYM_LBOUND:
3808 case GFC_ISYM_UBOUND:
3810 gfc_expr *arg;
3812 /* This is the variant without DIM=... */
3813 gcc_assert (expr->value.function.actual->next->expr == NULL);
3815 arg = expr->value.function.actual->expr;
3816 if (arg->rank == -1)
3818 gfc_se se;
3819 tree rank, tmp;
3821 /* The rank (hence the return value's shape) is unknown,
3822 we have to retrieve it. */
3823 gfc_init_se (&se, NULL);
3824 se.descriptor_only = 1;
3825 gfc_conv_expr (&se, arg);
3826 /* This is a bare variable, so there is no preliminary
3827 or cleanup code. */
3828 gcc_assert (se.pre.head == NULL_TREE
3829 && se.post.head == NULL_TREE);
3830 rank = gfc_conv_descriptor_rank (se.expr);
3831 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3832 gfc_array_index_type,
3833 fold_convert (gfc_array_index_type,
3834 rank),
3835 gfc_index_one_node);
3836 info->end[0] = gfc_evaluate_now (tmp, &loop->pre);
3837 info->start[0] = gfc_index_zero_node;
3838 info->stride[0] = gfc_index_one_node;
3839 continue;
3841 /* Otherwise fall through GFC_SS_FUNCTION. */
3843 case GFC_ISYM_LCOBOUND:
3844 case GFC_ISYM_UCOBOUND:
3845 case GFC_ISYM_THIS_IMAGE:
3846 break;
3848 default:
3849 continue;
3852 case GFC_SS_CONSTRUCTOR:
3853 case GFC_SS_FUNCTION:
3854 for (n = 0; n < ss->dimen; n++)
3856 int dim = ss->dim[n];
3858 info->start[dim] = gfc_index_zero_node;
3859 info->end[dim] = gfc_index_zero_node;
3860 info->stride[dim] = gfc_index_one_node;
3862 break;
3864 default:
3865 break;
3869 /* The rest is just runtime bound checking. */
3870 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3872 stmtblock_t block;
3873 tree lbound, ubound;
3874 tree end;
3875 tree size[GFC_MAX_DIMENSIONS];
3876 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
3877 gfc_array_info *info;
3878 char *msg;
3879 int dim;
3881 gfc_start_block (&block);
3883 for (n = 0; n < loop->dimen; n++)
3884 size[n] = NULL_TREE;
3886 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3888 stmtblock_t inner;
3889 gfc_ss_info *ss_info;
3890 gfc_expr *expr;
3891 locus *expr_loc;
3892 const char *expr_name;
3894 ss_info = ss->info;
3895 if (ss_info->type != GFC_SS_SECTION)
3896 continue;
3898 /* Catch allocatable lhs in f2003. */
3899 if (gfc_option.flag_realloc_lhs && ss->is_alloc_lhs)
3900 continue;
3902 expr = ss_info->expr;
3903 expr_loc = &expr->where;
3904 expr_name = expr->symtree->name;
3906 gfc_start_block (&inner);
3908 /* TODO: range checking for mapped dimensions. */
3909 info = &ss_info->data.array;
3911 /* This code only checks ranges. Elemental and vector
3912 dimensions are checked later. */
3913 for (n = 0; n < loop->dimen; n++)
3915 bool check_upper;
3917 dim = ss->dim[n];
3918 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
3919 continue;
3921 if (dim == info->ref->u.ar.dimen - 1
3922 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
3923 check_upper = false;
3924 else
3925 check_upper = true;
3927 /* Zero stride is not allowed. */
3928 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
3929 info->stride[dim], gfc_index_zero_node);
3930 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
3931 "of array '%s'", dim + 1, expr_name);
3932 gfc_trans_runtime_check (true, false, tmp, &inner,
3933 expr_loc, msg);
3934 free (msg);
3936 desc = info->descriptor;
3938 /* This is the run-time equivalent of resolve.c's
3939 check_dimension(). The logical is more readable there
3940 than it is here, with all the trees. */
3941 lbound = gfc_conv_array_lbound (desc, dim);
3942 end = info->end[dim];
3943 if (check_upper)
3944 ubound = gfc_conv_array_ubound (desc, dim);
3945 else
3946 ubound = NULL;
3948 /* non_zerosized is true when the selected range is not
3949 empty. */
3950 stride_pos = fold_build2_loc (input_location, GT_EXPR,
3951 boolean_type_node, info->stride[dim],
3952 gfc_index_zero_node);
3953 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3954 info->start[dim], end);
3955 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3956 boolean_type_node, stride_pos, tmp);
3958 stride_neg = fold_build2_loc (input_location, LT_EXPR,
3959 boolean_type_node,
3960 info->stride[dim], gfc_index_zero_node);
3961 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
3962 info->start[dim], end);
3963 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3964 boolean_type_node,
3965 stride_neg, tmp);
3966 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3967 boolean_type_node,
3968 stride_pos, stride_neg);
3970 /* Check the start of the range against the lower and upper
3971 bounds of the array, if the range is not empty.
3972 If upper bound is present, include both bounds in the
3973 error message. */
3974 if (check_upper)
3976 tmp = fold_build2_loc (input_location, LT_EXPR,
3977 boolean_type_node,
3978 info->start[dim], lbound);
3979 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3980 boolean_type_node,
3981 non_zerosized, tmp);
3982 tmp2 = fold_build2_loc (input_location, GT_EXPR,
3983 boolean_type_node,
3984 info->start[dim], ubound);
3985 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3986 boolean_type_node,
3987 non_zerosized, tmp2);
3988 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3989 "outside of expected range (%%ld:%%ld)",
3990 dim + 1, expr_name);
3991 gfc_trans_runtime_check (true, false, tmp, &inner,
3992 expr_loc, msg,
3993 fold_convert (long_integer_type_node, info->start[dim]),
3994 fold_convert (long_integer_type_node, lbound),
3995 fold_convert (long_integer_type_node, ubound));
3996 gfc_trans_runtime_check (true, false, tmp2, &inner,
3997 expr_loc, msg,
3998 fold_convert (long_integer_type_node, info->start[dim]),
3999 fold_convert (long_integer_type_node, lbound),
4000 fold_convert (long_integer_type_node, ubound));
4001 free (msg);
4003 else
4005 tmp = fold_build2_loc (input_location, LT_EXPR,
4006 boolean_type_node,
4007 info->start[dim], lbound);
4008 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4009 boolean_type_node, non_zerosized, tmp);
4010 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
4011 "below lower bound of %%ld",
4012 dim + 1, expr_name);
4013 gfc_trans_runtime_check (true, false, tmp, &inner,
4014 expr_loc, msg,
4015 fold_convert (long_integer_type_node, info->start[dim]),
4016 fold_convert (long_integer_type_node, lbound));
4017 free (msg);
4020 /* Compute the last element of the range, which is not
4021 necessarily "end" (think 0:5:3, which doesn't contain 5)
4022 and check it against both lower and upper bounds. */
4024 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4025 gfc_array_index_type, end,
4026 info->start[dim]);
4027 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
4028 gfc_array_index_type, tmp,
4029 info->stride[dim]);
4030 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4031 gfc_array_index_type, end, tmp);
4032 tmp2 = fold_build2_loc (input_location, LT_EXPR,
4033 boolean_type_node, tmp, lbound);
4034 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4035 boolean_type_node, non_zerosized, tmp2);
4036 if (check_upper)
4038 tmp3 = fold_build2_loc (input_location, GT_EXPR,
4039 boolean_type_node, tmp, ubound);
4040 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4041 boolean_type_node, non_zerosized, tmp3);
4042 asprintf (&msg, "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, tmp2, &inner,
4046 expr_loc, msg,
4047 fold_convert (long_integer_type_node, tmp),
4048 fold_convert (long_integer_type_node, ubound),
4049 fold_convert (long_integer_type_node, lbound));
4050 gfc_trans_runtime_check (true, false, tmp3, &inner,
4051 expr_loc, msg,
4052 fold_convert (long_integer_type_node, tmp),
4053 fold_convert (long_integer_type_node, ubound),
4054 fold_convert (long_integer_type_node, lbound));
4055 free (msg);
4057 else
4059 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
4060 "below lower bound of %%ld",
4061 dim + 1, expr_name);
4062 gfc_trans_runtime_check (true, false, tmp2, &inner,
4063 expr_loc, msg,
4064 fold_convert (long_integer_type_node, tmp),
4065 fold_convert (long_integer_type_node, lbound));
4066 free (msg);
4069 /* Check the section sizes match. */
4070 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4071 gfc_array_index_type, end,
4072 info->start[dim]);
4073 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4074 gfc_array_index_type, tmp,
4075 info->stride[dim]);
4076 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4077 gfc_array_index_type,
4078 gfc_index_one_node, tmp);
4079 tmp = fold_build2_loc (input_location, MAX_EXPR,
4080 gfc_array_index_type, tmp,
4081 build_int_cst (gfc_array_index_type, 0));
4082 /* We remember the size of the first section, and check all the
4083 others against this. */
4084 if (size[n])
4086 tmp3 = fold_build2_loc (input_location, NE_EXPR,
4087 boolean_type_node, tmp, size[n]);
4088 asprintf (&msg, "Array bound mismatch for dimension %d "
4089 "of array '%s' (%%ld/%%ld)",
4090 dim + 1, expr_name);
4092 gfc_trans_runtime_check (true, false, tmp3, &inner,
4093 expr_loc, msg,
4094 fold_convert (long_integer_type_node, tmp),
4095 fold_convert (long_integer_type_node, size[n]));
4097 free (msg);
4099 else
4100 size[n] = gfc_evaluate_now (tmp, &inner);
4103 tmp = gfc_finish_block (&inner);
4105 /* For optional arguments, only check bounds if the argument is
4106 present. */
4107 if (expr->symtree->n.sym->attr.optional
4108 || expr->symtree->n.sym->attr.not_always_present)
4109 tmp = build3_v (COND_EXPR,
4110 gfc_conv_expr_present (expr->symtree->n.sym),
4111 tmp, build_empty_stmt (input_location));
4113 gfc_add_expr_to_block (&block, tmp);
4117 tmp = gfc_finish_block (&block);
4118 gfc_add_expr_to_block (&loop->pre, tmp);
4121 for (loop = loop->nested; loop; loop = loop->next)
4122 gfc_conv_ss_startstride (loop);
4125 /* Return true if both symbols could refer to the same data object. Does
4126 not take account of aliasing due to equivalence statements. */
4128 static int
4129 symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
4130 bool lsym_target, bool rsym_pointer, bool rsym_target)
4132 /* Aliasing isn't possible if the symbols have different base types. */
4133 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
4134 return 0;
4136 /* Pointers can point to other pointers and target objects. */
4138 if ((lsym_pointer && (rsym_pointer || rsym_target))
4139 || (rsym_pointer && (lsym_pointer || lsym_target)))
4140 return 1;
4142 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
4143 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
4144 checked above. */
4145 if (lsym_target && rsym_target
4146 && ((lsym->attr.dummy && !lsym->attr.contiguous
4147 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
4148 || (rsym->attr.dummy && !rsym->attr.contiguous
4149 && (!rsym->attr.dimension
4150 || rsym->as->type == AS_ASSUMED_SHAPE))))
4151 return 1;
4153 return 0;
4157 /* Return true if the two SS could be aliased, i.e. both point to the same data
4158 object. */
4159 /* TODO: resolve aliases based on frontend expressions. */
4161 static int
4162 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
4164 gfc_ref *lref;
4165 gfc_ref *rref;
4166 gfc_expr *lexpr, *rexpr;
4167 gfc_symbol *lsym;
4168 gfc_symbol *rsym;
4169 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
4171 lexpr = lss->info->expr;
4172 rexpr = rss->info->expr;
4174 lsym = lexpr->symtree->n.sym;
4175 rsym = rexpr->symtree->n.sym;
4177 lsym_pointer = lsym->attr.pointer;
4178 lsym_target = lsym->attr.target;
4179 rsym_pointer = rsym->attr.pointer;
4180 rsym_target = rsym->attr.target;
4182 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
4183 rsym_pointer, rsym_target))
4184 return 1;
4186 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
4187 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
4188 return 0;
4190 /* For derived types we must check all the component types. We can ignore
4191 array references as these will have the same base type as the previous
4192 component ref. */
4193 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
4195 if (lref->type != REF_COMPONENT)
4196 continue;
4198 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
4199 lsym_target = lsym_target || lref->u.c.sym->attr.target;
4201 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
4202 rsym_pointer, rsym_target))
4203 return 1;
4205 if ((lsym_pointer && (rsym_pointer || rsym_target))
4206 || (rsym_pointer && (lsym_pointer || lsym_target)))
4208 if (gfc_compare_types (&lref->u.c.component->ts,
4209 &rsym->ts))
4210 return 1;
4213 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
4214 rref = rref->next)
4216 if (rref->type != REF_COMPONENT)
4217 continue;
4219 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4220 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4222 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
4223 lsym_pointer, lsym_target,
4224 rsym_pointer, rsym_target))
4225 return 1;
4227 if ((lsym_pointer && (rsym_pointer || rsym_target))
4228 || (rsym_pointer && (lsym_pointer || lsym_target)))
4230 if (gfc_compare_types (&lref->u.c.component->ts,
4231 &rref->u.c.sym->ts))
4232 return 1;
4233 if (gfc_compare_types (&lref->u.c.sym->ts,
4234 &rref->u.c.component->ts))
4235 return 1;
4236 if (gfc_compare_types (&lref->u.c.component->ts,
4237 &rref->u.c.component->ts))
4238 return 1;
4243 lsym_pointer = lsym->attr.pointer;
4244 lsym_target = lsym->attr.target;
4245 lsym_pointer = lsym->attr.pointer;
4246 lsym_target = lsym->attr.target;
4248 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
4250 if (rref->type != REF_COMPONENT)
4251 break;
4253 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4254 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4256 if (symbols_could_alias (rref->u.c.sym, lsym,
4257 lsym_pointer, lsym_target,
4258 rsym_pointer, rsym_target))
4259 return 1;
4261 if ((lsym_pointer && (rsym_pointer || rsym_target))
4262 || (rsym_pointer && (lsym_pointer || lsym_target)))
4264 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
4265 return 1;
4269 return 0;
4273 /* Resolve array data dependencies. Creates a temporary if required. */
4274 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
4275 dependency.c. */
4277 void
4278 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
4279 gfc_ss * rss)
4281 gfc_ss *ss;
4282 gfc_ref *lref;
4283 gfc_ref *rref;
4284 gfc_expr *dest_expr;
4285 gfc_expr *ss_expr;
4286 int nDepend = 0;
4287 int i, j;
4289 loop->temp_ss = NULL;
4290 dest_expr = dest->info->expr;
4292 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
4294 if (ss->info->type != GFC_SS_SECTION)
4295 continue;
4297 ss_expr = ss->info->expr;
4299 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
4301 if (gfc_could_be_alias (dest, ss)
4302 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
4304 nDepend = 1;
4305 break;
4308 else
4310 lref = dest_expr->ref;
4311 rref = ss_expr->ref;
4313 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
4315 if (nDepend == 1)
4316 break;
4318 for (i = 0; i < dest->dimen; i++)
4319 for (j = 0; j < ss->dimen; j++)
4320 if (i != j
4321 && dest->dim[i] == ss->dim[j])
4323 /* If we don't access array elements in the same order,
4324 there is a dependency. */
4325 nDepend = 1;
4326 goto temporary;
4328 #if 0
4329 /* TODO : loop shifting. */
4330 if (nDepend == 1)
4332 /* Mark the dimensions for LOOP SHIFTING */
4333 for (n = 0; n < loop->dimen; n++)
4335 int dim = dest->data.info.dim[n];
4337 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
4338 depends[n] = 2;
4339 else if (! gfc_is_same_range (&lref->u.ar,
4340 &rref->u.ar, dim, 0))
4341 depends[n] = 1;
4344 /* Put all the dimensions with dependencies in the
4345 innermost loops. */
4346 dim = 0;
4347 for (n = 0; n < loop->dimen; n++)
4349 gcc_assert (loop->order[n] == n);
4350 if (depends[n])
4351 loop->order[dim++] = n;
4353 for (n = 0; n < loop->dimen; n++)
4355 if (! depends[n])
4356 loop->order[dim++] = n;
4359 gcc_assert (dim == loop->dimen);
4360 break;
4362 #endif
4366 temporary:
4368 if (nDepend == 1)
4370 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
4371 if (GFC_ARRAY_TYPE_P (base_type)
4372 || GFC_DESCRIPTOR_TYPE_P (base_type))
4373 base_type = gfc_get_element_type (base_type);
4374 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
4375 loop->dimen);
4376 gfc_add_ss_to_loop (loop, loop->temp_ss);
4378 else
4379 loop->temp_ss = NULL;
4383 /* Browse through each array's information from the scalarizer and set the loop
4384 bounds according to the "best" one (per dimension), i.e. the one which
4385 provides the most information (constant bounds, shape, etc.). */
4387 static void
4388 set_loop_bounds (gfc_loopinfo *loop)
4390 int n, dim, spec_dim;
4391 gfc_array_info *info;
4392 gfc_array_info *specinfo;
4393 gfc_ss *ss;
4394 tree tmp;
4395 gfc_ss **loopspec;
4396 bool dynamic[GFC_MAX_DIMENSIONS];
4397 mpz_t *cshape;
4398 mpz_t i;
4399 bool nonoptional_arr;
4401 loopspec = loop->specloop;
4403 mpz_init (i);
4404 for (n = 0; n < loop->dimen; n++)
4406 loopspec[n] = NULL;
4407 dynamic[n] = false;
4409 /* If there are both optional and nonoptional array arguments, scalarize
4410 over the nonoptional; otherwise, it does not matter as then all
4411 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
4413 nonoptional_arr = false;
4415 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4416 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
4417 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
4418 nonoptional_arr = true;
4420 /* We use one SS term, and use that to determine the bounds of the
4421 loop for this dimension. We try to pick the simplest term. */
4422 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4424 gfc_ss_type ss_type;
4426 ss_type = ss->info->type;
4427 if (ss_type == GFC_SS_SCALAR
4428 || ss_type == GFC_SS_TEMP
4429 || ss_type == GFC_SS_REFERENCE
4430 || (ss->info->can_be_null_ref && nonoptional_arr))
4431 continue;
4433 info = &ss->info->data.array;
4434 dim = ss->dim[n];
4436 if (loopspec[n] != NULL)
4438 specinfo = &loopspec[n]->info->data.array;
4439 spec_dim = loopspec[n]->dim[n];
4441 else
4443 /* Silence uninitialized warnings. */
4444 specinfo = NULL;
4445 spec_dim = 0;
4448 if (info->shape)
4450 gcc_assert (info->shape[dim]);
4451 /* The frontend has worked out the size for us. */
4452 if (!loopspec[n]
4453 || !specinfo->shape
4454 || !integer_zerop (specinfo->start[spec_dim]))
4455 /* Prefer zero-based descriptors if possible. */
4456 loopspec[n] = ss;
4457 continue;
4460 if (ss_type == GFC_SS_CONSTRUCTOR)
4462 gfc_constructor_base base;
4463 /* An unknown size constructor will always be rank one.
4464 Higher rank constructors will either have known shape,
4465 or still be wrapped in a call to reshape. */
4466 gcc_assert (loop->dimen == 1);
4468 /* Always prefer to use the constructor bounds if the size
4469 can be determined at compile time. Prefer not to otherwise,
4470 since the general case involves realloc, and it's better to
4471 avoid that overhead if possible. */
4472 base = ss->info->expr->value.constructor;
4473 dynamic[n] = gfc_get_array_constructor_size (&i, base);
4474 if (!dynamic[n] || !loopspec[n])
4475 loopspec[n] = ss;
4476 continue;
4479 /* Avoid using an allocatable lhs in an assignment, since
4480 there might be a reallocation coming. */
4481 if (loopspec[n] && ss->is_alloc_lhs)
4482 continue;
4484 if (!loopspec[n])
4485 loopspec[n] = ss;
4486 /* Criteria for choosing a loop specifier (most important first):
4487 doesn't need realloc
4488 stride of one
4489 known stride
4490 known lower bound
4491 known upper bound
4493 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
4494 loopspec[n] = ss;
4495 else if (integer_onep (info->stride[dim])
4496 && !integer_onep (specinfo->stride[spec_dim]))
4497 loopspec[n] = ss;
4498 else if (INTEGER_CST_P (info->stride[dim])
4499 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
4500 loopspec[n] = ss;
4501 else if (INTEGER_CST_P (info->start[dim])
4502 && !INTEGER_CST_P (specinfo->start[spec_dim])
4503 && integer_onep (info->stride[dim])
4504 == integer_onep (specinfo->stride[spec_dim])
4505 && INTEGER_CST_P (info->stride[dim])
4506 == INTEGER_CST_P (specinfo->stride[spec_dim]))
4507 loopspec[n] = ss;
4508 /* We don't work out the upper bound.
4509 else if (INTEGER_CST_P (info->finish[n])
4510 && ! INTEGER_CST_P (specinfo->finish[n]))
4511 loopspec[n] = ss; */
4514 /* We should have found the scalarization loop specifier. If not,
4515 that's bad news. */
4516 gcc_assert (loopspec[n]);
4518 info = &loopspec[n]->info->data.array;
4519 dim = loopspec[n]->dim[n];
4521 /* Set the extents of this range. */
4522 cshape = info->shape;
4523 if (cshape && INTEGER_CST_P (info->start[dim])
4524 && INTEGER_CST_P (info->stride[dim]))
4526 loop->from[n] = info->start[dim];
4527 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
4528 mpz_sub_ui (i, i, 1);
4529 /* To = from + (size - 1) * stride. */
4530 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
4531 if (!integer_onep (info->stride[dim]))
4532 tmp = fold_build2_loc (input_location, MULT_EXPR,
4533 gfc_array_index_type, tmp,
4534 info->stride[dim]);
4535 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
4536 gfc_array_index_type,
4537 loop->from[n], tmp);
4539 else
4541 loop->from[n] = info->start[dim];
4542 switch (loopspec[n]->info->type)
4544 case GFC_SS_CONSTRUCTOR:
4545 /* The upper bound is calculated when we expand the
4546 constructor. */
4547 gcc_assert (loop->to[n] == NULL_TREE);
4548 break;
4550 case GFC_SS_SECTION:
4551 /* Use the end expression if it exists and is not constant,
4552 so that it is only evaluated once. */
4553 loop->to[n] = info->end[dim];
4554 break;
4556 case GFC_SS_FUNCTION:
4557 /* The loop bound will be set when we generate the call. */
4558 gcc_assert (loop->to[n] == NULL_TREE);
4559 break;
4561 case GFC_SS_INTRINSIC:
4563 gfc_expr *expr = loopspec[n]->info->expr;
4565 /* The {l,u}bound of an assumed rank. */
4566 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
4567 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
4568 && expr->value.function.actual->next->expr == NULL
4569 && expr->value.function.actual->expr->rank == -1);
4571 loop->to[n] = info->end[dim];
4572 break;
4575 default:
4576 gcc_unreachable ();
4580 /* Transform everything so we have a simple incrementing variable. */
4581 if (integer_onep (info->stride[dim]))
4582 info->delta[dim] = gfc_index_zero_node;
4583 else
4585 /* Set the delta for this section. */
4586 info->delta[dim] = gfc_evaluate_now (loop->from[n], &loop->pre);
4587 /* Number of iterations is (end - start + step) / step.
4588 with start = 0, this simplifies to
4589 last = end / step;
4590 for (i = 0; i<=last; i++){...}; */
4591 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4592 gfc_array_index_type, loop->to[n],
4593 loop->from[n]);
4594 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4595 gfc_array_index_type, tmp, info->stride[dim]);
4596 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
4597 tmp, build_int_cst (gfc_array_index_type, -1));
4598 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
4599 /* Make the loop variable start at 0. */
4600 loop->from[n] = gfc_index_zero_node;
4603 mpz_clear (i);
4605 for (loop = loop->nested; loop; loop = loop->next)
4606 set_loop_bounds (loop);
4610 /* Initialize the scalarization loop. Creates the loop variables. Determines
4611 the range of the loop variables. Creates a temporary if required.
4612 Also generates code for scalar expressions which have been
4613 moved outside the loop. */
4615 void
4616 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
4618 gfc_ss *tmp_ss;
4619 tree tmp;
4621 set_loop_bounds (loop);
4623 /* Add all the scalar code that can be taken out of the loops.
4624 This may include calculating the loop bounds, so do it before
4625 allocating the temporary. */
4626 gfc_add_loop_ss_code (loop, loop->ss, false, where);
4628 tmp_ss = loop->temp_ss;
4629 /* If we want a temporary then create it. */
4630 if (tmp_ss != NULL)
4632 gfc_ss_info *tmp_ss_info;
4634 tmp_ss_info = tmp_ss->info;
4635 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
4636 gcc_assert (loop->parent == NULL);
4638 /* Make absolutely sure that this is a complete type. */
4639 if (tmp_ss_info->string_length)
4640 tmp_ss_info->data.temp.type
4641 = gfc_get_character_type_len_for_eltype
4642 (TREE_TYPE (tmp_ss_info->data.temp.type),
4643 tmp_ss_info->string_length);
4645 tmp = tmp_ss_info->data.temp.type;
4646 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
4647 tmp_ss_info->type = GFC_SS_SECTION;
4649 gcc_assert (tmp_ss->dimen != 0);
4651 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
4652 NULL_TREE, false, true, false, where);
4655 /* For array parameters we don't have loop variables, so don't calculate the
4656 translations. */
4657 if (!loop->array_parameter)
4658 gfc_set_delta (loop);
4662 /* Calculates how to transform from loop variables to array indices for each
4663 array: once loop bounds are chosen, sets the difference (DELTA field) between
4664 loop bounds and array reference bounds, for each array info. */
4666 void
4667 gfc_set_delta (gfc_loopinfo *loop)
4669 gfc_ss *ss, **loopspec;
4670 gfc_array_info *info;
4671 tree tmp;
4672 int n, dim;
4674 loopspec = loop->specloop;
4676 /* Calculate the translation from loop variables to array indices. */
4677 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4679 gfc_ss_type ss_type;
4681 ss_type = ss->info->type;
4682 if (ss_type != GFC_SS_SECTION
4683 && ss_type != GFC_SS_COMPONENT
4684 && ss_type != GFC_SS_CONSTRUCTOR)
4685 continue;
4687 info = &ss->info->data.array;
4689 for (n = 0; n < ss->dimen; n++)
4691 /* If we are specifying the range the delta is already set. */
4692 if (loopspec[n] != ss)
4694 dim = ss->dim[n];
4696 /* Calculate the offset relative to the loop variable.
4697 First multiply by the stride. */
4698 tmp = loop->from[n];
4699 if (!integer_onep (info->stride[dim]))
4700 tmp = fold_build2_loc (input_location, MULT_EXPR,
4701 gfc_array_index_type,
4702 tmp, info->stride[dim]);
4704 /* Then subtract this from our starting value. */
4705 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4706 gfc_array_index_type,
4707 info->start[dim], tmp);
4709 info->delta[dim] = gfc_evaluate_now (tmp, &loop->pre);
4714 for (loop = loop->nested; loop; loop = loop->next)
4715 gfc_set_delta (loop);
4719 /* Calculate the size of a given array dimension from the bounds. This
4720 is simply (ubound - lbound + 1) if this expression is positive
4721 or 0 if it is negative (pick either one if it is zero). Optionally
4722 (if or_expr is present) OR the (expression != 0) condition to it. */
4724 tree
4725 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
4727 tree res;
4728 tree cond;
4730 /* Calculate (ubound - lbound + 1). */
4731 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4732 ubound, lbound);
4733 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
4734 gfc_index_one_node);
4736 /* Check whether the size for this dimension is negative. */
4737 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, res,
4738 gfc_index_zero_node);
4739 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
4740 gfc_index_zero_node, res);
4742 /* Build OR expression. */
4743 if (or_expr)
4744 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4745 boolean_type_node, *or_expr, cond);
4747 return res;
4751 /* For an array descriptor, get the total number of elements. This is just
4752 the product of the extents along from_dim to to_dim. */
4754 static tree
4755 gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
4757 tree res;
4758 int dim;
4760 res = gfc_index_one_node;
4762 for (dim = from_dim; dim < to_dim; ++dim)
4764 tree lbound;
4765 tree ubound;
4766 tree extent;
4768 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
4769 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
4771 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
4772 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4773 res, extent);
4776 return res;
4780 /* Full size of an array. */
4782 tree
4783 gfc_conv_descriptor_size (tree desc, int rank)
4785 return gfc_conv_descriptor_size_1 (desc, 0, rank);
4789 /* Size of a coarray for all dimensions but the last. */
4791 tree
4792 gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
4794 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
4798 /* Fills in an array descriptor, and returns the size of the array.
4799 The size will be a simple_val, ie a variable or a constant. Also
4800 calculates the offset of the base. The pointer argument overflow,
4801 which should be of integer type, will increase in value if overflow
4802 occurs during the size calculation. Returns the size of the array.
4804 stride = 1;
4805 offset = 0;
4806 for (n = 0; n < rank; n++)
4808 a.lbound[n] = specified_lower_bound;
4809 offset = offset + a.lbond[n] * stride;
4810 size = 1 - lbound;
4811 a.ubound[n] = specified_upper_bound;
4812 a.stride[n] = stride;
4813 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
4814 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
4815 stride = stride * size;
4817 for (n = rank; n < rank+corank; n++)
4818 (Set lcobound/ucobound as above.)
4819 element_size = sizeof (array element);
4820 if (!rank)
4821 return element_size
4822 stride = (size_t) stride;
4823 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
4824 stride = stride * element_size;
4825 return (stride);
4826 } */
4827 /*GCC ARRAYS*/
4829 static tree
4830 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
4831 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
4832 stmtblock_t * descriptor_block, tree * overflow,
4833 tree expr3_elem_size, tree *nelems, gfc_expr *expr3)
4835 tree type;
4836 tree tmp;
4837 tree size;
4838 tree offset;
4839 tree stride;
4840 tree element_size;
4841 tree or_expr;
4842 tree thencase;
4843 tree elsecase;
4844 tree cond;
4845 tree var;
4846 stmtblock_t thenblock;
4847 stmtblock_t elseblock;
4848 gfc_expr *ubound;
4849 gfc_se se;
4850 int n;
4852 type = TREE_TYPE (descriptor);
4854 stride = gfc_index_one_node;
4855 offset = gfc_index_zero_node;
4857 /* Set the dtype. */
4858 tmp = gfc_conv_descriptor_dtype (descriptor);
4859 gfc_add_modify (descriptor_block, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
4861 or_expr = boolean_false_node;
4863 for (n = 0; n < rank; n++)
4865 tree conv_lbound;
4866 tree conv_ubound;
4868 /* We have 3 possibilities for determining the size of the array:
4869 lower == NULL => lbound = 1, ubound = upper[n]
4870 upper[n] = NULL => lbound = 1, ubound = lower[n]
4871 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
4872 ubound = upper[n];
4874 /* Set lower bound. */
4875 gfc_init_se (&se, NULL);
4876 if (lower == NULL)
4877 se.expr = gfc_index_one_node;
4878 else
4880 gcc_assert (lower[n]);
4881 if (ubound)
4883 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
4884 gfc_add_block_to_block (pblock, &se.pre);
4886 else
4888 se.expr = gfc_index_one_node;
4889 ubound = lower[n];
4892 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
4893 gfc_rank_cst[n], se.expr);
4894 conv_lbound = se.expr;
4896 /* Work out the offset for this component. */
4897 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4898 se.expr, stride);
4899 offset = fold_build2_loc (input_location, MINUS_EXPR,
4900 gfc_array_index_type, offset, tmp);
4902 /* Set upper bound. */
4903 gfc_init_se (&se, NULL);
4904 gcc_assert (ubound);
4905 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
4906 gfc_add_block_to_block (pblock, &se.pre);
4908 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
4909 gfc_rank_cst[n], se.expr);
4910 conv_ubound = se.expr;
4912 /* Store the stride. */
4913 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
4914 gfc_rank_cst[n], stride);
4916 /* Calculate size and check whether extent is negative. */
4917 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
4918 size = gfc_evaluate_now (size, pblock);
4920 /* Check whether multiplying the stride by the number of
4921 elements in this dimension would overflow. We must also check
4922 whether the current dimension has zero size in order to avoid
4923 division by zero.
4925 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
4926 gfc_array_index_type,
4927 fold_convert (gfc_array_index_type,
4928 TYPE_MAX_VALUE (gfc_array_index_type)),
4929 size);
4930 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
4931 boolean_type_node, tmp, stride));
4932 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4933 integer_one_node, integer_zero_node);
4934 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
4935 boolean_type_node, size,
4936 gfc_index_zero_node));
4937 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4938 integer_zero_node, tmp);
4939 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
4940 *overflow, tmp);
4941 *overflow = gfc_evaluate_now (tmp, pblock);
4943 /* Multiply the stride by the number of elements in this dimension. */
4944 stride = fold_build2_loc (input_location, MULT_EXPR,
4945 gfc_array_index_type, stride, size);
4946 stride = gfc_evaluate_now (stride, pblock);
4949 for (n = rank; n < rank + corank; n++)
4951 ubound = upper[n];
4953 /* Set lower bound. */
4954 gfc_init_se (&se, NULL);
4955 if (lower == NULL || lower[n] == NULL)
4957 gcc_assert (n == rank + corank - 1);
4958 se.expr = gfc_index_one_node;
4960 else
4962 if (ubound || n == rank + corank - 1)
4964 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
4965 gfc_add_block_to_block (pblock, &se.pre);
4967 else
4969 se.expr = gfc_index_one_node;
4970 ubound = lower[n];
4973 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
4974 gfc_rank_cst[n], se.expr);
4976 if (n < rank + corank - 1)
4978 gfc_init_se (&se, NULL);
4979 gcc_assert (ubound);
4980 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
4981 gfc_add_block_to_block (pblock, &se.pre);
4982 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
4983 gfc_rank_cst[n], se.expr);
4987 /* The stride is the number of elements in the array, so multiply by the
4988 size of an element to get the total size. Obviously, if there is a
4989 SOURCE expression (expr3) we must use its element size. */
4990 if (expr3_elem_size != NULL_TREE)
4991 tmp = expr3_elem_size;
4992 else if (expr3 != NULL)
4994 if (expr3->ts.type == BT_CLASS)
4996 gfc_se se_sz;
4997 gfc_expr *sz = gfc_copy_expr (expr3);
4998 gfc_add_vptr_component (sz);
4999 gfc_add_size_component (sz);
5000 gfc_init_se (&se_sz, NULL);
5001 gfc_conv_expr (&se_sz, sz);
5002 gfc_free_expr (sz);
5003 tmp = se_sz.expr;
5005 else
5007 tmp = gfc_typenode_for_spec (&expr3->ts);
5008 tmp = TYPE_SIZE_UNIT (tmp);
5011 else
5012 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5014 /* Convert to size_t. */
5015 element_size = fold_convert (size_type_node, tmp);
5017 if (rank == 0)
5018 return element_size;
5020 *nelems = gfc_evaluate_now (stride, pblock);
5021 stride = fold_convert (size_type_node, stride);
5023 /* First check for overflow. Since an array of type character can
5024 have zero element_size, we must check for that before
5025 dividing. */
5026 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5027 size_type_node,
5028 TYPE_MAX_VALUE (size_type_node), element_size);
5029 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5030 boolean_type_node, tmp, stride));
5031 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5032 integer_one_node, integer_zero_node);
5033 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5034 boolean_type_node, element_size,
5035 build_int_cst (size_type_node, 0)));
5036 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5037 integer_zero_node, tmp);
5038 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5039 *overflow, tmp);
5040 *overflow = gfc_evaluate_now (tmp, pblock);
5042 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
5043 stride, element_size);
5045 if (poffset != NULL)
5047 offset = gfc_evaluate_now (offset, pblock);
5048 *poffset = offset;
5051 if (integer_zerop (or_expr))
5052 return size;
5053 if (integer_onep (or_expr))
5054 return build_int_cst (size_type_node, 0);
5056 var = gfc_create_var (TREE_TYPE (size), "size");
5057 gfc_start_block (&thenblock);
5058 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
5059 thencase = gfc_finish_block (&thenblock);
5061 gfc_start_block (&elseblock);
5062 gfc_add_modify (&elseblock, var, size);
5063 elsecase = gfc_finish_block (&elseblock);
5065 tmp = gfc_evaluate_now (or_expr, pblock);
5066 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
5067 gfc_add_expr_to_block (pblock, tmp);
5069 return var;
5073 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
5074 the work for an ALLOCATE statement. */
5075 /*GCC ARRAYS*/
5077 bool
5078 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
5079 tree errlen, tree label_finish, tree expr3_elem_size,
5080 tree *nelems, gfc_expr *expr3)
5082 tree tmp;
5083 tree pointer;
5084 tree offset = NULL_TREE;
5085 tree token = NULL_TREE;
5086 tree size;
5087 tree msg;
5088 tree error = NULL_TREE;
5089 tree overflow; /* Boolean storing whether size calculation overflows. */
5090 tree var_overflow = NULL_TREE;
5091 tree cond;
5092 tree set_descriptor;
5093 stmtblock_t set_descriptor_block;
5094 stmtblock_t elseblock;
5095 gfc_expr **lower;
5096 gfc_expr **upper;
5097 gfc_ref *ref, *prev_ref = NULL;
5098 bool allocatable, coarray, dimension;
5100 ref = expr->ref;
5102 /* Find the last reference in the chain. */
5103 while (ref && ref->next != NULL)
5105 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
5106 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
5107 prev_ref = ref;
5108 ref = ref->next;
5111 if (ref == NULL || ref->type != REF_ARRAY)
5112 return false;
5114 if (!prev_ref)
5116 allocatable = expr->symtree->n.sym->attr.allocatable;
5117 coarray = expr->symtree->n.sym->attr.codimension;
5118 dimension = expr->symtree->n.sym->attr.dimension;
5120 else
5122 allocatable = prev_ref->u.c.component->attr.allocatable;
5123 coarray = prev_ref->u.c.component->attr.codimension;
5124 dimension = prev_ref->u.c.component->attr.dimension;
5127 if (!dimension)
5128 gcc_assert (coarray);
5130 /* Figure out the size of the array. */
5131 switch (ref->u.ar.type)
5133 case AR_ELEMENT:
5134 if (!coarray)
5136 lower = NULL;
5137 upper = ref->u.ar.start;
5138 break;
5140 /* Fall through. */
5142 case AR_SECTION:
5143 lower = ref->u.ar.start;
5144 upper = ref->u.ar.end;
5145 break;
5147 case AR_FULL:
5148 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
5150 lower = ref->u.ar.as->lower;
5151 upper = ref->u.ar.as->upper;
5152 break;
5154 default:
5155 gcc_unreachable ();
5156 break;
5159 overflow = integer_zero_node;
5161 gfc_init_block (&set_descriptor_block);
5162 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
5163 ref->u.ar.as->corank, &offset, lower, upper,
5164 &se->pre, &set_descriptor_block, &overflow,
5165 expr3_elem_size, nelems, expr3);
5167 if (dimension)
5170 var_overflow = gfc_create_var (integer_type_node, "overflow");
5171 gfc_add_modify (&se->pre, var_overflow, overflow);
5173 /* Generate the block of code handling overflow. */
5174 msg = gfc_build_addr_expr (pchar_type_node,
5175 gfc_build_localized_cstring_const
5176 ("Integer overflow when calculating the amount of "
5177 "memory to allocate"));
5178 error = build_call_expr_loc (input_location, gfor_fndecl_runtime_error,
5179 1, msg);
5182 if (status != NULL_TREE)
5184 tree status_type = TREE_TYPE (status);
5185 stmtblock_t set_status_block;
5187 gfc_start_block (&set_status_block);
5188 gfc_add_modify (&set_status_block, status,
5189 build_int_cst (status_type, LIBERROR_ALLOCATION));
5190 error = gfc_finish_block (&set_status_block);
5193 gfc_start_block (&elseblock);
5195 /* Allocate memory to store the data. */
5196 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
5197 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
5199 pointer = gfc_conv_descriptor_data_get (se->expr);
5200 STRIP_NOPS (pointer);
5202 if (coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
5203 token = gfc_build_addr_expr (NULL_TREE,
5204 gfc_conv_descriptor_token (se->expr));
5206 /* The allocatable variant takes the old pointer as first argument. */
5207 if (allocatable)
5208 gfc_allocate_allocatable (&elseblock, pointer, size, token,
5209 status, errmsg, errlen, label_finish, expr);
5210 else
5211 gfc_allocate_using_malloc (&elseblock, pointer, size, status);
5213 if (dimension)
5215 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
5216 boolean_type_node, var_overflow, integer_zero_node));
5217 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
5218 error, gfc_finish_block (&elseblock));
5220 else
5221 tmp = gfc_finish_block (&elseblock);
5223 gfc_add_expr_to_block (&se->pre, tmp);
5225 if (expr->ts.type == BT_CLASS)
5227 tmp = build_int_cst (unsigned_char_type_node, 0);
5228 /* With class objects, it is best to play safe and null the
5229 memory because we cannot know if dynamic types have allocatable
5230 components or not. */
5231 tmp = build_call_expr_loc (input_location,
5232 builtin_decl_explicit (BUILT_IN_MEMSET),
5233 3, pointer, tmp, size);
5234 gfc_add_expr_to_block (&se->pre, tmp);
5237 /* Update the array descriptors. */
5238 if (dimension)
5239 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
5241 set_descriptor = gfc_finish_block (&set_descriptor_block);
5242 if (status != NULL_TREE)
5244 cond = fold_build2_loc (input_location, EQ_EXPR,
5245 boolean_type_node, status,
5246 build_int_cst (TREE_TYPE (status), 0));
5247 gfc_add_expr_to_block (&se->pre,
5248 fold_build3_loc (input_location, COND_EXPR, void_type_node,
5249 gfc_likely (cond), set_descriptor,
5250 build_empty_stmt (input_location)));
5252 else
5253 gfc_add_expr_to_block (&se->pre, set_descriptor);
5255 if ((expr->ts.type == BT_DERIVED)
5256 && expr->ts.u.derived->attr.alloc_comp)
5258 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, se->expr,
5259 ref->u.ar.as->rank);
5260 gfc_add_expr_to_block (&se->pre, tmp);
5263 return true;
5267 /* Deallocate an array variable. Also used when an allocated variable goes
5268 out of scope. */
5269 /*GCC ARRAYS*/
5271 tree
5272 gfc_array_deallocate (tree descriptor, tree pstat, tree errmsg, tree errlen,
5273 tree label_finish, gfc_expr* expr)
5275 tree var;
5276 tree tmp;
5277 stmtblock_t block;
5278 bool coarray = gfc_is_coarray (expr);
5280 gfc_start_block (&block);
5282 /* Get a pointer to the data. */
5283 var = gfc_conv_descriptor_data_get (descriptor);
5284 STRIP_NOPS (var);
5286 /* Parameter is the address of the data component. */
5287 tmp = gfc_deallocate_with_status (coarray ? descriptor : var, pstat, errmsg,
5288 errlen, label_finish, false, expr, coarray);
5289 gfc_add_expr_to_block (&block, tmp);
5291 /* Zero the data pointer; only for coarrays an error can occur and then
5292 the allocation status may not be changed. */
5293 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5294 var, build_int_cst (TREE_TYPE (var), 0));
5295 if (pstat != NULL_TREE && coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
5297 tree cond;
5298 tree stat = build_fold_indirect_ref_loc (input_location, pstat);
5300 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5301 stat, build_int_cst (TREE_TYPE (stat), 0));
5302 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5303 cond, tmp, build_empty_stmt (input_location));
5306 gfc_add_expr_to_block (&block, tmp);
5308 return gfc_finish_block (&block);
5312 /* Create an array constructor from an initialization expression.
5313 We assume the frontend already did any expansions and conversions. */
5315 tree
5316 gfc_conv_array_initializer (tree type, gfc_expr * expr)
5318 gfc_constructor *c;
5319 tree tmp;
5320 gfc_se se;
5321 HOST_WIDE_INT hi;
5322 unsigned HOST_WIDE_INT lo;
5323 tree index, range;
5324 vec<constructor_elt, va_gc> *v = NULL;
5326 if (expr->expr_type == EXPR_VARIABLE
5327 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
5328 && expr->symtree->n.sym->value)
5329 expr = expr->symtree->n.sym->value;
5331 switch (expr->expr_type)
5333 case EXPR_CONSTANT:
5334 case EXPR_STRUCTURE:
5335 /* A single scalar or derived type value. Create an array with all
5336 elements equal to that value. */
5337 gfc_init_se (&se, NULL);
5339 if (expr->expr_type == EXPR_CONSTANT)
5340 gfc_conv_constant (&se, expr);
5341 else
5342 gfc_conv_structure (&se, expr, 1);
5344 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5345 gcc_assert (tmp && INTEGER_CST_P (tmp));
5346 hi = TREE_INT_CST_HIGH (tmp);
5347 lo = TREE_INT_CST_LOW (tmp);
5348 lo++;
5349 if (lo == 0)
5350 hi++;
5351 /* This will probably eat buckets of memory for large arrays. */
5352 while (hi != 0 || lo != 0)
5354 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
5355 if (lo == 0)
5356 hi--;
5357 lo--;
5359 break;
5361 case EXPR_ARRAY:
5362 /* Create a vector of all the elements. */
5363 for (c = gfc_constructor_first (expr->value.constructor);
5364 c; c = gfc_constructor_next (c))
5366 if (c->iterator)
5368 /* Problems occur when we get something like
5369 integer :: a(lots) = (/(i, i=1, lots)/) */
5370 gfc_fatal_error ("The number of elements in the array constructor "
5371 "at %L requires an increase of the allowed %d "
5372 "upper limit. See -fmax-array-constructor "
5373 "option", &expr->where,
5374 gfc_option.flag_max_array_constructor);
5375 return NULL_TREE;
5377 if (mpz_cmp_si (c->offset, 0) != 0)
5378 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5379 else
5380 index = NULL_TREE;
5382 if (mpz_cmp_si (c->repeat, 1) > 0)
5384 tree tmp1, tmp2;
5385 mpz_t maxval;
5387 mpz_init (maxval);
5388 mpz_add (maxval, c->offset, c->repeat);
5389 mpz_sub_ui (maxval, maxval, 1);
5390 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5391 if (mpz_cmp_si (c->offset, 0) != 0)
5393 mpz_add_ui (maxval, c->offset, 1);
5394 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5396 else
5397 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5399 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
5400 mpz_clear (maxval);
5402 else
5403 range = NULL;
5405 gfc_init_se (&se, NULL);
5406 switch (c->expr->expr_type)
5408 case EXPR_CONSTANT:
5409 gfc_conv_constant (&se, c->expr);
5410 break;
5412 case EXPR_STRUCTURE:
5413 gfc_conv_structure (&se, c->expr, 1);
5414 break;
5416 default:
5417 /* Catch those occasional beasts that do not simplify
5418 for one reason or another, assuming that if they are
5419 standard defying the frontend will catch them. */
5420 gfc_conv_expr (&se, c->expr);
5421 break;
5424 if (range == NULL_TREE)
5425 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5426 else
5428 if (index != NULL_TREE)
5429 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5430 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
5433 break;
5435 case EXPR_NULL:
5436 return gfc_build_null_descriptor (type);
5438 default:
5439 gcc_unreachable ();
5442 /* Create a constructor from the list of elements. */
5443 tmp = build_constructor (type, v);
5444 TREE_CONSTANT (tmp) = 1;
5445 return tmp;
5449 /* Generate code to evaluate non-constant coarray cobounds. */
5451 void
5452 gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
5453 const gfc_symbol *sym)
5455 int dim;
5456 tree ubound;
5457 tree lbound;
5458 gfc_se se;
5459 gfc_array_spec *as;
5461 as = sym->as;
5463 for (dim = as->rank; dim < as->rank + as->corank; dim++)
5465 /* Evaluate non-constant array bound expressions. */
5466 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
5467 if (as->lower[dim] && !INTEGER_CST_P (lbound))
5469 gfc_init_se (&se, NULL);
5470 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
5471 gfc_add_block_to_block (pblock, &se.pre);
5472 gfc_add_modify (pblock, lbound, se.expr);
5474 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
5475 if (as->upper[dim] && !INTEGER_CST_P (ubound))
5477 gfc_init_se (&se, NULL);
5478 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
5479 gfc_add_block_to_block (pblock, &se.pre);
5480 gfc_add_modify (pblock, ubound, se.expr);
5486 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
5487 returns the size (in elements) of the array. */
5489 static tree
5490 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
5491 stmtblock_t * pblock)
5493 gfc_array_spec *as;
5494 tree size;
5495 tree stride;
5496 tree offset;
5497 tree ubound;
5498 tree lbound;
5499 tree tmp;
5500 gfc_se se;
5502 int dim;
5504 as = sym->as;
5506 size = gfc_index_one_node;
5507 offset = gfc_index_zero_node;
5508 for (dim = 0; dim < as->rank; dim++)
5510 /* Evaluate non-constant array bound expressions. */
5511 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
5512 if (as->lower[dim] && !INTEGER_CST_P (lbound))
5514 gfc_init_se (&se, NULL);
5515 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
5516 gfc_add_block_to_block (pblock, &se.pre);
5517 gfc_add_modify (pblock, lbound, se.expr);
5519 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
5520 if (as->upper[dim] && !INTEGER_CST_P (ubound))
5522 gfc_init_se (&se, NULL);
5523 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
5524 gfc_add_block_to_block (pblock, &se.pre);
5525 gfc_add_modify (pblock, ubound, se.expr);
5527 /* The offset of this dimension. offset = offset - lbound * stride. */
5528 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5529 lbound, size);
5530 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5531 offset, tmp);
5533 /* The size of this dimension, and the stride of the next. */
5534 if (dim + 1 < as->rank)
5535 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
5536 else
5537 stride = GFC_TYPE_ARRAY_SIZE (type);
5539 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
5541 /* Calculate stride = size * (ubound + 1 - lbound). */
5542 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5543 gfc_array_index_type,
5544 gfc_index_one_node, lbound);
5545 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5546 gfc_array_index_type, ubound, tmp);
5547 tmp = fold_build2_loc (input_location, MULT_EXPR,
5548 gfc_array_index_type, size, tmp);
5549 if (stride)
5550 gfc_add_modify (pblock, stride, tmp);
5551 else
5552 stride = gfc_evaluate_now (tmp, pblock);
5554 /* Make sure that negative size arrays are translated
5555 to being zero size. */
5556 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
5557 stride, gfc_index_zero_node);
5558 tmp = fold_build3_loc (input_location, COND_EXPR,
5559 gfc_array_index_type, tmp,
5560 stride, gfc_index_zero_node);
5561 gfc_add_modify (pblock, stride, tmp);
5564 size = stride;
5567 gfc_trans_array_cobounds (type, pblock, sym);
5568 gfc_trans_vla_type_sizes (sym, pblock);
5570 *poffset = offset;
5571 return size;
5575 /* Generate code to initialize/allocate an array variable. */
5577 void
5578 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
5579 gfc_wrapped_block * block)
5581 stmtblock_t init;
5582 tree type;
5583 tree tmp = NULL_TREE;
5584 tree size;
5585 tree offset;
5586 tree space;
5587 tree inittree;
5588 bool onstack;
5590 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
5592 /* Do nothing for USEd variables. */
5593 if (sym->attr.use_assoc)
5594 return;
5596 type = TREE_TYPE (decl);
5597 gcc_assert (GFC_ARRAY_TYPE_P (type));
5598 onstack = TREE_CODE (type) != POINTER_TYPE;
5600 gfc_init_block (&init);
5602 /* Evaluate character string length. */
5603 if (sym->ts.type == BT_CHARACTER
5604 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
5606 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5608 gfc_trans_vla_type_sizes (sym, &init);
5610 /* Emit a DECL_EXPR for this variable, which will cause the
5611 gimplifier to allocate storage, and all that good stuff. */
5612 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
5613 gfc_add_expr_to_block (&init, tmp);
5616 if (onstack)
5618 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5619 return;
5622 type = TREE_TYPE (type);
5624 gcc_assert (!sym->attr.use_assoc);
5625 gcc_assert (!TREE_STATIC (decl));
5626 gcc_assert (!sym->module);
5628 if (sym->ts.type == BT_CHARACTER
5629 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
5630 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5632 size = gfc_trans_array_bounds (type, sym, &offset, &init);
5634 /* Don't actually allocate space for Cray Pointees. */
5635 if (sym->attr.cray_pointee)
5637 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5638 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5640 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5641 return;
5644 if (gfc_option.flag_stack_arrays)
5646 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
5647 space = build_decl (sym->declared_at.lb->location,
5648 VAR_DECL, create_tmp_var_name ("A"),
5649 TREE_TYPE (TREE_TYPE (decl)));
5650 gfc_trans_vla_type_sizes (sym, &init);
5652 else
5654 /* The size is the number of elements in the array, so multiply by the
5655 size of an element to get the total size. */
5656 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5657 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5658 size, fold_convert (gfc_array_index_type, tmp));
5660 /* Allocate memory to hold the data. */
5661 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
5662 gfc_add_modify (&init, decl, tmp);
5664 /* Free the temporary. */
5665 tmp = gfc_call_free (convert (pvoid_type_node, decl));
5666 space = NULL_TREE;
5669 /* Set offset of the array. */
5670 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5671 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5673 /* Automatic arrays should not have initializers. */
5674 gcc_assert (!sym->value);
5676 inittree = gfc_finish_block (&init);
5678 if (space)
5680 tree addr;
5681 pushdecl (space);
5683 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
5684 where also space is located. */
5685 gfc_init_block (&init);
5686 tmp = fold_build1_loc (input_location, DECL_EXPR,
5687 TREE_TYPE (space), space);
5688 gfc_add_expr_to_block (&init, tmp);
5689 addr = fold_build1_loc (sym->declared_at.lb->location,
5690 ADDR_EXPR, TREE_TYPE (decl), space);
5691 gfc_add_modify (&init, decl, addr);
5692 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5693 tmp = NULL_TREE;
5695 gfc_add_init_cleanup (block, inittree, tmp);
5699 /* Generate entry and exit code for g77 calling convention arrays. */
5701 void
5702 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
5704 tree parm;
5705 tree type;
5706 locus loc;
5707 tree offset;
5708 tree tmp;
5709 tree stmt;
5710 stmtblock_t init;
5712 gfc_save_backend_locus (&loc);
5713 gfc_set_backend_locus (&sym->declared_at);
5715 /* Descriptor type. */
5716 parm = sym->backend_decl;
5717 type = TREE_TYPE (parm);
5718 gcc_assert (GFC_ARRAY_TYPE_P (type));
5720 gfc_start_block (&init);
5722 if (sym->ts.type == BT_CHARACTER
5723 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
5724 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5726 /* Evaluate the bounds of the array. */
5727 gfc_trans_array_bounds (type, sym, &offset, &init);
5729 /* Set the offset. */
5730 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5731 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5733 /* Set the pointer itself if we aren't using the parameter directly. */
5734 if (TREE_CODE (parm) != PARM_DECL)
5736 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
5737 gfc_add_modify (&init, parm, tmp);
5739 stmt = gfc_finish_block (&init);
5741 gfc_restore_backend_locus (&loc);
5743 /* Add the initialization code to the start of the function. */
5745 if (sym->attr.optional || sym->attr.not_always_present)
5747 tmp = gfc_conv_expr_present (sym);
5748 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
5751 gfc_add_init_cleanup (block, stmt, NULL_TREE);
5755 /* Modify the descriptor of an array parameter so that it has the
5756 correct lower bound. Also move the upper bound accordingly.
5757 If the array is not packed, it will be copied into a temporary.
5758 For each dimension we set the new lower and upper bounds. Then we copy the
5759 stride and calculate the offset for this dimension. We also work out
5760 what the stride of a packed array would be, and see it the two match.
5761 If the array need repacking, we set the stride to the values we just
5762 calculated, recalculate the offset and copy the array data.
5763 Code is also added to copy the data back at the end of the function.
5766 void
5767 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
5768 gfc_wrapped_block * block)
5770 tree size;
5771 tree type;
5772 tree offset;
5773 locus loc;
5774 stmtblock_t init;
5775 tree stmtInit, stmtCleanup;
5776 tree lbound;
5777 tree ubound;
5778 tree dubound;
5779 tree dlbound;
5780 tree dumdesc;
5781 tree tmp;
5782 tree stride, stride2;
5783 tree stmt_packed;
5784 tree stmt_unpacked;
5785 tree partial;
5786 gfc_se se;
5787 int n;
5788 int checkparm;
5789 int no_repack;
5790 bool optional_arg;
5792 /* Do nothing for pointer and allocatable arrays. */
5793 if (sym->attr.pointer || sym->attr.allocatable)
5794 return;
5796 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
5798 gfc_trans_g77_array (sym, block);
5799 return;
5802 gfc_save_backend_locus (&loc);
5803 gfc_set_backend_locus (&sym->declared_at);
5805 /* Descriptor type. */
5806 type = TREE_TYPE (tmpdesc);
5807 gcc_assert (GFC_ARRAY_TYPE_P (type));
5808 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5809 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
5810 gfc_start_block (&init);
5812 if (sym->ts.type == BT_CHARACTER
5813 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
5814 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5816 checkparm = (sym->as->type == AS_EXPLICIT
5817 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
5819 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
5820 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
5822 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
5824 /* For non-constant shape arrays we only check if the first dimension
5825 is contiguous. Repacking higher dimensions wouldn't gain us
5826 anything as we still don't know the array stride. */
5827 partial = gfc_create_var (boolean_type_node, "partial");
5828 TREE_USED (partial) = 1;
5829 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
5830 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, tmp,
5831 gfc_index_one_node);
5832 gfc_add_modify (&init, partial, tmp);
5834 else
5835 partial = NULL_TREE;
5837 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
5838 here, however I think it does the right thing. */
5839 if (no_repack)
5841 /* Set the first stride. */
5842 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
5843 stride = gfc_evaluate_now (stride, &init);
5845 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5846 stride, gfc_index_zero_node);
5847 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
5848 tmp, gfc_index_one_node, stride);
5849 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
5850 gfc_add_modify (&init, stride, tmp);
5852 /* Allow the user to disable array repacking. */
5853 stmt_unpacked = NULL_TREE;
5855 else
5857 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
5858 /* A library call to repack the array if necessary. */
5859 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5860 stmt_unpacked = build_call_expr_loc (input_location,
5861 gfor_fndecl_in_pack, 1, tmp);
5863 stride = gfc_index_one_node;
5865 if (gfc_option.warn_array_temp)
5866 gfc_warning ("Creating array temporary at %L", &loc);
5869 /* This is for the case where the array data is used directly without
5870 calling the repack function. */
5871 if (no_repack || partial != NULL_TREE)
5872 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
5873 else
5874 stmt_packed = NULL_TREE;
5876 /* Assign the data pointer. */
5877 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
5879 /* Don't repack unknown shape arrays when the first stride is 1. */
5880 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
5881 partial, stmt_packed, stmt_unpacked);
5883 else
5884 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
5885 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
5887 offset = gfc_index_zero_node;
5888 size = gfc_index_one_node;
5890 /* Evaluate the bounds of the array. */
5891 for (n = 0; n < sym->as->rank; n++)
5893 if (checkparm || !sym->as->upper[n])
5895 /* Get the bounds of the actual parameter. */
5896 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
5897 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
5899 else
5901 dubound = NULL_TREE;
5902 dlbound = NULL_TREE;
5905 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
5906 if (!INTEGER_CST_P (lbound))
5908 gfc_init_se (&se, NULL);
5909 gfc_conv_expr_type (&se, sym->as->lower[n],
5910 gfc_array_index_type);
5911 gfc_add_block_to_block (&init, &se.pre);
5912 gfc_add_modify (&init, lbound, se.expr);
5915 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
5916 /* Set the desired upper bound. */
5917 if (sym->as->upper[n])
5919 /* We know what we want the upper bound to be. */
5920 if (!INTEGER_CST_P (ubound))
5922 gfc_init_se (&se, NULL);
5923 gfc_conv_expr_type (&se, sym->as->upper[n],
5924 gfc_array_index_type);
5925 gfc_add_block_to_block (&init, &se.pre);
5926 gfc_add_modify (&init, ubound, se.expr);
5929 /* Check the sizes match. */
5930 if (checkparm)
5932 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
5933 char * msg;
5934 tree temp;
5936 temp = fold_build2_loc (input_location, MINUS_EXPR,
5937 gfc_array_index_type, ubound, lbound);
5938 temp = fold_build2_loc (input_location, PLUS_EXPR,
5939 gfc_array_index_type,
5940 gfc_index_one_node, temp);
5941 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
5942 gfc_array_index_type, dubound,
5943 dlbound);
5944 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
5945 gfc_array_index_type,
5946 gfc_index_one_node, stride2);
5947 tmp = fold_build2_loc (input_location, NE_EXPR,
5948 gfc_array_index_type, temp, stride2);
5949 asprintf (&msg, "Dimension %d of array '%s' has extent "
5950 "%%ld instead of %%ld", n+1, sym->name);
5952 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
5953 fold_convert (long_integer_type_node, temp),
5954 fold_convert (long_integer_type_node, stride2));
5956 free (msg);
5959 else
5961 /* For assumed shape arrays move the upper bound by the same amount
5962 as the lower bound. */
5963 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5964 gfc_array_index_type, dubound, dlbound);
5965 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5966 gfc_array_index_type, tmp, lbound);
5967 gfc_add_modify (&init, ubound, tmp);
5969 /* The offset of this dimension. offset = offset - lbound * stride. */
5970 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5971 lbound, stride);
5972 offset = fold_build2_loc (input_location, MINUS_EXPR,
5973 gfc_array_index_type, offset, tmp);
5975 /* The size of this dimension, and the stride of the next. */
5976 if (n + 1 < sym->as->rank)
5978 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
5980 if (no_repack || partial != NULL_TREE)
5981 stmt_unpacked =
5982 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
5984 /* Figure out the stride if not a known constant. */
5985 if (!INTEGER_CST_P (stride))
5987 if (no_repack)
5988 stmt_packed = NULL_TREE;
5989 else
5991 /* Calculate stride = size * (ubound + 1 - lbound). */
5992 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5993 gfc_array_index_type,
5994 gfc_index_one_node, lbound);
5995 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5996 gfc_array_index_type, ubound, tmp);
5997 size = fold_build2_loc (input_location, MULT_EXPR,
5998 gfc_array_index_type, size, tmp);
5999 stmt_packed = size;
6002 /* Assign the stride. */
6003 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6004 tmp = fold_build3_loc (input_location, COND_EXPR,
6005 gfc_array_index_type, partial,
6006 stmt_unpacked, stmt_packed);
6007 else
6008 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
6009 gfc_add_modify (&init, stride, tmp);
6012 else
6014 stride = GFC_TYPE_ARRAY_SIZE (type);
6016 if (stride && !INTEGER_CST_P (stride))
6018 /* Calculate size = stride * (ubound + 1 - lbound). */
6019 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6020 gfc_array_index_type,
6021 gfc_index_one_node, lbound);
6022 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6023 gfc_array_index_type,
6024 ubound, tmp);
6025 tmp = fold_build2_loc (input_location, MULT_EXPR,
6026 gfc_array_index_type,
6027 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
6028 gfc_add_modify (&init, stride, tmp);
6033 gfc_trans_array_cobounds (type, &init, sym);
6035 /* Set the offset. */
6036 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
6037 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6039 gfc_trans_vla_type_sizes (sym, &init);
6041 stmtInit = gfc_finish_block (&init);
6043 /* Only do the entry/initialization code if the arg is present. */
6044 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6045 optional_arg = (sym->attr.optional
6046 || (sym->ns->proc_name->attr.entry_master
6047 && sym->attr.dummy));
6048 if (optional_arg)
6050 tmp = gfc_conv_expr_present (sym);
6051 stmtInit = build3_v (COND_EXPR, tmp, stmtInit,
6052 build_empty_stmt (input_location));
6055 /* Cleanup code. */
6056 if (no_repack)
6057 stmtCleanup = NULL_TREE;
6058 else
6060 stmtblock_t cleanup;
6061 gfc_start_block (&cleanup);
6063 if (sym->attr.intent != INTENT_IN)
6065 /* Copy the data back. */
6066 tmp = build_call_expr_loc (input_location,
6067 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
6068 gfc_add_expr_to_block (&cleanup, tmp);
6071 /* Free the temporary. */
6072 tmp = gfc_call_free (tmpdesc);
6073 gfc_add_expr_to_block (&cleanup, tmp);
6075 stmtCleanup = gfc_finish_block (&cleanup);
6077 /* Only do the cleanup if the array was repacked. */
6078 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
6079 tmp = gfc_conv_descriptor_data_get (tmp);
6080 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6081 tmp, tmpdesc);
6082 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6083 build_empty_stmt (input_location));
6085 if (optional_arg)
6087 tmp = gfc_conv_expr_present (sym);
6088 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6089 build_empty_stmt (input_location));
6093 /* We don't need to free any memory allocated by internal_pack as it will
6094 be freed at the end of the function by pop_context. */
6095 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
6097 gfc_restore_backend_locus (&loc);
6101 /* Calculate the overall offset, including subreferences. */
6102 static void
6103 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
6104 bool subref, gfc_expr *expr)
6106 tree tmp;
6107 tree field;
6108 tree stride;
6109 tree index;
6110 gfc_ref *ref;
6111 gfc_se start;
6112 int n;
6114 /* If offset is NULL and this is not a subreferenced array, there is
6115 nothing to do. */
6116 if (offset == NULL_TREE)
6118 if (subref)
6119 offset = gfc_index_zero_node;
6120 else
6121 return;
6124 tmp = build_array_ref (desc, offset, NULL);
6126 /* Offset the data pointer for pointer assignments from arrays with
6127 subreferences; e.g. my_integer => my_type(:)%integer_component. */
6128 if (subref)
6130 /* Go past the array reference. */
6131 for (ref = expr->ref; ref; ref = ref->next)
6132 if (ref->type == REF_ARRAY &&
6133 ref->u.ar.type != AR_ELEMENT)
6135 ref = ref->next;
6136 break;
6139 /* Calculate the offset for each subsequent subreference. */
6140 for (; ref; ref = ref->next)
6142 switch (ref->type)
6144 case REF_COMPONENT:
6145 field = ref->u.c.component->backend_decl;
6146 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6147 tmp = fold_build3_loc (input_location, COMPONENT_REF,
6148 TREE_TYPE (field),
6149 tmp, field, NULL_TREE);
6150 break;
6152 case REF_SUBSTRING:
6153 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
6154 gfc_init_se (&start, NULL);
6155 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
6156 gfc_add_block_to_block (block, &start.pre);
6157 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
6158 break;
6160 case REF_ARRAY:
6161 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
6162 && ref->u.ar.type == AR_ELEMENT);
6164 /* TODO - Add bounds checking. */
6165 stride = gfc_index_one_node;
6166 index = gfc_index_zero_node;
6167 for (n = 0; n < ref->u.ar.dimen; n++)
6169 tree itmp;
6170 tree jtmp;
6172 /* Update the index. */
6173 gfc_init_se (&start, NULL);
6174 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
6175 itmp = gfc_evaluate_now (start.expr, block);
6176 gfc_init_se (&start, NULL);
6177 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
6178 jtmp = gfc_evaluate_now (start.expr, block);
6179 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6180 gfc_array_index_type, itmp, jtmp);
6181 itmp = fold_build2_loc (input_location, MULT_EXPR,
6182 gfc_array_index_type, itmp, stride);
6183 index = fold_build2_loc (input_location, PLUS_EXPR,
6184 gfc_array_index_type, itmp, index);
6185 index = gfc_evaluate_now (index, block);
6187 /* Update the stride. */
6188 gfc_init_se (&start, NULL);
6189 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
6190 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6191 gfc_array_index_type, start.expr,
6192 jtmp);
6193 itmp = fold_build2_loc (input_location, PLUS_EXPR,
6194 gfc_array_index_type,
6195 gfc_index_one_node, itmp);
6196 stride = fold_build2_loc (input_location, MULT_EXPR,
6197 gfc_array_index_type, stride, itmp);
6198 stride = gfc_evaluate_now (stride, block);
6201 /* Apply the index to obtain the array element. */
6202 tmp = gfc_build_array_ref (tmp, index, NULL);
6203 break;
6205 default:
6206 gcc_unreachable ();
6207 break;
6212 /* Set the target data pointer. */
6213 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
6214 gfc_conv_descriptor_data_set (block, parm, offset);
6218 /* gfc_conv_expr_descriptor needs the string length an expression
6219 so that the size of the temporary can be obtained. This is done
6220 by adding up the string lengths of all the elements in the
6221 expression. Function with non-constant expressions have their
6222 string lengths mapped onto the actual arguments using the
6223 interface mapping machinery in trans-expr.c. */
6224 static void
6225 get_array_charlen (gfc_expr *expr, gfc_se *se)
6227 gfc_interface_mapping mapping;
6228 gfc_formal_arglist *formal;
6229 gfc_actual_arglist *arg;
6230 gfc_se tse;
6232 if (expr->ts.u.cl->length
6233 && gfc_is_constant_expr (expr->ts.u.cl->length))
6235 if (!expr->ts.u.cl->backend_decl)
6236 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6237 return;
6240 switch (expr->expr_type)
6242 case EXPR_OP:
6243 get_array_charlen (expr->value.op.op1, se);
6245 /* For parentheses the expression ts.u.cl is identical. */
6246 if (expr->value.op.op == INTRINSIC_PARENTHESES)
6247 return;
6249 expr->ts.u.cl->backend_decl =
6250 gfc_create_var (gfc_charlen_type_node, "sln");
6252 if (expr->value.op.op2)
6254 get_array_charlen (expr->value.op.op2, se);
6256 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
6258 /* Add the string lengths and assign them to the expression
6259 string length backend declaration. */
6260 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6261 fold_build2_loc (input_location, PLUS_EXPR,
6262 gfc_charlen_type_node,
6263 expr->value.op.op1->ts.u.cl->backend_decl,
6264 expr->value.op.op2->ts.u.cl->backend_decl));
6266 else
6267 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6268 expr->value.op.op1->ts.u.cl->backend_decl);
6269 break;
6271 case EXPR_FUNCTION:
6272 if (expr->value.function.esym == NULL
6273 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
6275 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6276 break;
6279 /* Map expressions involving the dummy arguments onto the actual
6280 argument expressions. */
6281 gfc_init_interface_mapping (&mapping);
6282 formal = gfc_sym_get_dummy_args (expr->symtree->n.sym);
6283 arg = expr->value.function.actual;
6285 /* Set se = NULL in the calls to the interface mapping, to suppress any
6286 backend stuff. */
6287 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
6289 if (!arg->expr)
6290 continue;
6291 if (formal->sym)
6292 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
6295 gfc_init_se (&tse, NULL);
6297 /* Build the expression for the character length and convert it. */
6298 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
6300 gfc_add_block_to_block (&se->pre, &tse.pre);
6301 gfc_add_block_to_block (&se->post, &tse.post);
6302 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
6303 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
6304 gfc_charlen_type_node, tse.expr,
6305 build_int_cst (gfc_charlen_type_node, 0));
6306 expr->ts.u.cl->backend_decl = tse.expr;
6307 gfc_free_interface_mapping (&mapping);
6308 break;
6310 default:
6311 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6312 break;
6317 /* Helper function to check dimensions. */
6318 static bool
6319 transposed_dims (gfc_ss *ss)
6321 int n;
6323 for (n = 0; n < ss->dimen; n++)
6324 if (ss->dim[n] != n)
6325 return true;
6326 return false;
6330 /* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
6331 AR_FULL, suitable for the scalarizer. */
6333 static gfc_ss *
6334 walk_coarray (gfc_expr *e)
6336 gfc_ss *ss;
6338 gcc_assert (gfc_get_corank (e) > 0);
6340 ss = gfc_walk_expr (e);
6342 /* Fix scalar coarray. */
6343 if (ss == gfc_ss_terminator)
6345 gfc_ref *ref;
6347 ref = e->ref;
6348 while (ref)
6350 if (ref->type == REF_ARRAY
6351 && ref->u.ar.codimen > 0)
6352 break;
6354 ref = ref->next;
6357 gcc_assert (ref != NULL);
6358 if (ref->u.ar.type == AR_ELEMENT)
6359 ref->u.ar.type = AR_SECTION;
6360 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
6363 return ss;
6367 /* Convert an array for passing as an actual argument. Expressions and
6368 vector subscripts are evaluated and stored in a temporary, which is then
6369 passed. For whole arrays the descriptor is passed. For array sections
6370 a modified copy of the descriptor is passed, but using the original data.
6372 This function is also used for array pointer assignments, and there
6373 are three cases:
6375 - se->want_pointer && !se->direct_byref
6376 EXPR is an actual argument. On exit, se->expr contains a
6377 pointer to the array descriptor.
6379 - !se->want_pointer && !se->direct_byref
6380 EXPR is an actual argument to an intrinsic function or the
6381 left-hand side of a pointer assignment. On exit, se->expr
6382 contains the descriptor for EXPR.
6384 - !se->want_pointer && se->direct_byref
6385 EXPR is the right-hand side of a pointer assignment and
6386 se->expr is the descriptor for the previously-evaluated
6387 left-hand side. The function creates an assignment from
6388 EXPR to se->expr.
6391 The se->force_tmp flag disables the non-copying descriptor optimization
6392 that is used for transpose. It may be used in cases where there is an
6393 alias between the transpose argument and another argument in the same
6394 function call. */
6396 void
6397 gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
6399 gfc_ss *ss;
6400 gfc_ss_type ss_type;
6401 gfc_ss_info *ss_info;
6402 gfc_loopinfo loop;
6403 gfc_array_info *info;
6404 int need_tmp;
6405 int n;
6406 tree tmp;
6407 tree desc;
6408 stmtblock_t block;
6409 tree start;
6410 tree offset;
6411 int full;
6412 bool subref_array_target = false;
6413 gfc_expr *arg, *ss_expr;
6415 if (se->want_coarray)
6416 ss = walk_coarray (expr);
6417 else
6418 ss = gfc_walk_expr (expr);
6420 gcc_assert (ss != NULL);
6421 gcc_assert (ss != gfc_ss_terminator);
6423 ss_info = ss->info;
6424 ss_type = ss_info->type;
6425 ss_expr = ss_info->expr;
6427 /* Special case: TRANSPOSE which needs no temporary. */
6428 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
6429 && NULL != (arg = gfc_get_noncopying_intrinsic_argument (expr)))
6431 /* This is a call to transpose which has already been handled by the
6432 scalarizer, so that we just need to get its argument's descriptor. */
6433 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
6434 expr = expr->value.function.actual->expr;
6437 /* Special case things we know we can pass easily. */
6438 switch (expr->expr_type)
6440 case EXPR_VARIABLE:
6441 /* If we have a linear array section, we can pass it directly.
6442 Otherwise we need to copy it into a temporary. */
6444 gcc_assert (ss_type == GFC_SS_SECTION);
6445 gcc_assert (ss_expr == expr);
6446 info = &ss_info->data.array;
6448 /* Get the descriptor for the array. */
6449 gfc_conv_ss_descriptor (&se->pre, ss, 0);
6450 desc = info->descriptor;
6452 subref_array_target = se->direct_byref && is_subref_array (expr);
6453 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
6454 && !subref_array_target;
6456 if (se->force_tmp)
6457 need_tmp = 1;
6459 if (need_tmp)
6460 full = 0;
6461 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6463 /* Create a new descriptor if the array doesn't have one. */
6464 full = 0;
6466 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
6467 full = 1;
6468 else if (se->direct_byref)
6469 full = 0;
6470 else
6471 full = gfc_full_array_ref_p (info->ref, NULL);
6473 if (full && !transposed_dims (ss))
6475 if (se->direct_byref && !se->byref_noassign)
6477 /* Copy the descriptor for pointer assignments. */
6478 gfc_add_modify (&se->pre, se->expr, desc);
6480 /* Add any offsets from subreferences. */
6481 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
6482 subref_array_target, expr);
6484 else if (se->want_pointer)
6486 /* We pass full arrays directly. This means that pointers and
6487 allocatable arrays should also work. */
6488 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6490 else
6492 se->expr = desc;
6495 if (expr->ts.type == BT_CHARACTER)
6496 se->string_length = gfc_get_expr_charlen (expr);
6498 gfc_free_ss_chain (ss);
6499 return;
6501 break;
6503 case EXPR_FUNCTION:
6504 /* A transformational function return value will be a temporary
6505 array descriptor. We still need to go through the scalarizer
6506 to create the descriptor. Elemental functions are handled as
6507 arbitrary expressions, i.e. copy to a temporary. */
6509 if (se->direct_byref)
6511 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
6513 /* For pointer assignments pass the descriptor directly. */
6514 if (se->ss == NULL)
6515 se->ss = ss;
6516 else
6517 gcc_assert (se->ss == ss);
6518 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
6519 gfc_conv_expr (se, expr);
6520 gfc_free_ss_chain (ss);
6521 return;
6524 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
6526 if (ss_expr != expr)
6527 /* Elemental function. */
6528 gcc_assert ((expr->value.function.esym != NULL
6529 && expr->value.function.esym->attr.elemental)
6530 || (expr->value.function.isym != NULL
6531 && expr->value.function.isym->elemental)
6532 || gfc_inline_intrinsic_function_p (expr));
6533 else
6534 gcc_assert (ss_type == GFC_SS_INTRINSIC);
6536 need_tmp = 1;
6537 if (expr->ts.type == BT_CHARACTER
6538 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6539 get_array_charlen (expr, se);
6541 info = NULL;
6543 else
6545 /* Transformational function. */
6546 info = &ss_info->data.array;
6547 need_tmp = 0;
6549 break;
6551 case EXPR_ARRAY:
6552 /* Constant array constructors don't need a temporary. */
6553 if (ss_type == GFC_SS_CONSTRUCTOR
6554 && expr->ts.type != BT_CHARACTER
6555 && gfc_constant_array_constructor_p (expr->value.constructor))
6557 need_tmp = 0;
6558 info = &ss_info->data.array;
6560 else
6562 need_tmp = 1;
6563 info = NULL;
6565 break;
6567 default:
6568 /* Something complicated. Copy it into a temporary. */
6569 need_tmp = 1;
6570 info = NULL;
6571 break;
6574 /* If we are creating a temporary, we don't need to bother about aliases
6575 anymore. */
6576 if (need_tmp)
6577 se->force_tmp = 0;
6579 gfc_init_loopinfo (&loop);
6581 /* Associate the SS with the loop. */
6582 gfc_add_ss_to_loop (&loop, ss);
6584 /* Tell the scalarizer not to bother creating loop variables, etc. */
6585 if (!need_tmp)
6586 loop.array_parameter = 1;
6587 else
6588 /* The right-hand side of a pointer assignment mustn't use a temporary. */
6589 gcc_assert (!se->direct_byref);
6591 /* Setup the scalarizing loops and bounds. */
6592 gfc_conv_ss_startstride (&loop);
6594 if (need_tmp)
6596 if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
6597 get_array_charlen (expr, se);
6599 /* Tell the scalarizer to make a temporary. */
6600 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
6601 ((expr->ts.type == BT_CHARACTER)
6602 ? expr->ts.u.cl->backend_decl
6603 : NULL),
6604 loop.dimen);
6606 se->string_length = loop.temp_ss->info->string_length;
6607 gcc_assert (loop.temp_ss->dimen == loop.dimen);
6608 gfc_add_ss_to_loop (&loop, loop.temp_ss);
6611 gfc_conv_loop_setup (&loop, & expr->where);
6613 if (need_tmp)
6615 /* Copy into a temporary and pass that. We don't need to copy the data
6616 back because expressions and vector subscripts must be INTENT_IN. */
6617 /* TODO: Optimize passing function return values. */
6618 gfc_se lse;
6619 gfc_se rse;
6621 /* Start the copying loops. */
6622 gfc_mark_ss_chain_used (loop.temp_ss, 1);
6623 gfc_mark_ss_chain_used (ss, 1);
6624 gfc_start_scalarized_body (&loop, &block);
6626 /* Copy each data element. */
6627 gfc_init_se (&lse, NULL);
6628 gfc_copy_loopinfo_to_se (&lse, &loop);
6629 gfc_init_se (&rse, NULL);
6630 gfc_copy_loopinfo_to_se (&rse, &loop);
6632 lse.ss = loop.temp_ss;
6633 rse.ss = ss;
6635 gfc_conv_scalarized_array_ref (&lse, NULL);
6636 if (expr->ts.type == BT_CHARACTER)
6638 gfc_conv_expr (&rse, expr);
6639 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
6640 rse.expr = build_fold_indirect_ref_loc (input_location,
6641 rse.expr);
6643 else
6644 gfc_conv_expr_val (&rse, expr);
6646 gfc_add_block_to_block (&block, &rse.pre);
6647 gfc_add_block_to_block (&block, &lse.pre);
6649 lse.string_length = rse.string_length;
6650 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
6651 expr->expr_type == EXPR_VARIABLE
6652 || expr->expr_type == EXPR_ARRAY, true);
6653 gfc_add_expr_to_block (&block, tmp);
6655 /* Finish the copying loops. */
6656 gfc_trans_scalarizing_loops (&loop, &block);
6658 desc = loop.temp_ss->info->data.array.descriptor;
6660 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
6662 desc = info->descriptor;
6663 se->string_length = ss_info->string_length;
6665 else
6667 /* We pass sections without copying to a temporary. Make a new
6668 descriptor and point it at the section we want. The loop variable
6669 limits will be the limits of the section.
6670 A function may decide to repack the array to speed up access, but
6671 we're not bothered about that here. */
6672 int dim, ndim, codim;
6673 tree parm;
6674 tree parmtype;
6675 tree stride;
6676 tree from;
6677 tree to;
6678 tree base;
6680 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
6682 if (se->want_coarray)
6684 gfc_array_ref *ar = &info->ref->u.ar;
6686 codim = gfc_get_corank (expr);
6687 for (n = 0; n < codim - 1; n++)
6689 /* Make sure we are not lost somehow. */
6690 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
6692 /* Make sure the call to gfc_conv_section_startstride won't
6693 generate unnecessary code to calculate stride. */
6694 gcc_assert (ar->stride[n + ndim] == NULL);
6696 gfc_conv_section_startstride (&loop, ss, n + ndim);
6697 loop.from[n + loop.dimen] = info->start[n + ndim];
6698 loop.to[n + loop.dimen] = info->end[n + ndim];
6701 gcc_assert (n == codim - 1);
6702 evaluate_bound (&loop.pre, info->start, ar->start,
6703 info->descriptor, n + ndim, true);
6704 loop.from[n + loop.dimen] = info->start[n + ndim];
6706 else
6707 codim = 0;
6709 /* Set the string_length for a character array. */
6710 if (expr->ts.type == BT_CHARACTER)
6711 se->string_length = gfc_get_expr_charlen (expr);
6713 desc = info->descriptor;
6714 if (se->direct_byref && !se->byref_noassign)
6716 /* For pointer assignments we fill in the destination. */
6717 parm = se->expr;
6718 parmtype = TREE_TYPE (parm);
6720 else
6722 /* Otherwise make a new one. */
6723 parmtype = gfc_get_element_type (TREE_TYPE (desc));
6724 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
6725 loop.from, loop.to, 0,
6726 GFC_ARRAY_UNKNOWN, false);
6727 parm = gfc_create_var (parmtype, "parm");
6730 offset = gfc_index_zero_node;
6732 /* The following can be somewhat confusing. We have two
6733 descriptors, a new one and the original array.
6734 {parm, parmtype, dim} refer to the new one.
6735 {desc, type, n, loop} refer to the original, which maybe
6736 a descriptorless array.
6737 The bounds of the scalarization are the bounds of the section.
6738 We don't have to worry about numeric overflows when calculating
6739 the offsets because all elements are within the array data. */
6741 /* Set the dtype. */
6742 tmp = gfc_conv_descriptor_dtype (parm);
6743 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
6745 /* Set offset for assignments to pointer only to zero if it is not
6746 the full array. */
6747 if (se->direct_byref
6748 && info->ref && info->ref->u.ar.type != AR_FULL)
6749 base = gfc_index_zero_node;
6750 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6751 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
6752 else
6753 base = NULL_TREE;
6755 for (n = 0; n < ndim; n++)
6757 stride = gfc_conv_array_stride (desc, n);
6759 /* Work out the offset. */
6760 if (info->ref
6761 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6763 gcc_assert (info->subscript[n]
6764 && info->subscript[n]->info->type == GFC_SS_SCALAR);
6765 start = info->subscript[n]->info->data.scalar.value;
6767 else
6769 /* Evaluate and remember the start of the section. */
6770 start = info->start[n];
6771 stride = gfc_evaluate_now (stride, &loop.pre);
6774 tmp = gfc_conv_array_lbound (desc, n);
6775 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
6776 start, tmp);
6777 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
6778 tmp, stride);
6779 offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
6780 offset, tmp);
6782 if (info->ref
6783 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6785 /* For elemental dimensions, we only need the offset. */
6786 continue;
6789 /* Vector subscripts need copying and are handled elsewhere. */
6790 if (info->ref)
6791 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
6793 /* look for the corresponding scalarizer dimension: dim. */
6794 for (dim = 0; dim < ndim; dim++)
6795 if (ss->dim[dim] == n)
6796 break;
6798 /* loop exited early: the DIM being looked for has been found. */
6799 gcc_assert (dim < ndim);
6801 /* Set the new lower bound. */
6802 from = loop.from[dim];
6803 to = loop.to[dim];
6805 /* If we have an array section or are assigning make sure that
6806 the lower bound is 1. References to the full
6807 array should otherwise keep the original bounds. */
6808 if ((!info->ref
6809 || info->ref->u.ar.type != AR_FULL)
6810 && !integer_onep (from))
6812 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6813 gfc_array_index_type, gfc_index_one_node,
6814 from);
6815 to = fold_build2_loc (input_location, PLUS_EXPR,
6816 gfc_array_index_type, to, tmp);
6817 from = gfc_index_one_node;
6819 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
6820 gfc_rank_cst[dim], from);
6822 /* Set the new upper bound. */
6823 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
6824 gfc_rank_cst[dim], to);
6826 /* Multiply the stride by the section stride to get the
6827 total stride. */
6828 stride = fold_build2_loc (input_location, MULT_EXPR,
6829 gfc_array_index_type,
6830 stride, info->stride[n]);
6832 if (se->direct_byref
6833 && info->ref
6834 && info->ref->u.ar.type != AR_FULL)
6836 base = fold_build2_loc (input_location, MINUS_EXPR,
6837 TREE_TYPE (base), base, stride);
6839 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6841 tmp = gfc_conv_array_lbound (desc, n);
6842 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6843 TREE_TYPE (base), tmp, loop.from[dim]);
6844 tmp = fold_build2_loc (input_location, MULT_EXPR,
6845 TREE_TYPE (base), tmp,
6846 gfc_conv_array_stride (desc, n));
6847 base = fold_build2_loc (input_location, PLUS_EXPR,
6848 TREE_TYPE (base), tmp, base);
6851 /* Store the new stride. */
6852 gfc_conv_descriptor_stride_set (&loop.pre, parm,
6853 gfc_rank_cst[dim], stride);
6856 for (n = loop.dimen; n < loop.dimen + codim; n++)
6858 from = loop.from[n];
6859 to = loop.to[n];
6860 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
6861 gfc_rank_cst[n], from);
6862 if (n < loop.dimen + codim - 1)
6863 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
6864 gfc_rank_cst[n], to);
6867 if (se->data_not_needed)
6868 gfc_conv_descriptor_data_set (&loop.pre, parm,
6869 gfc_index_zero_node);
6870 else
6871 /* Point the data pointer at the 1st element in the section. */
6872 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
6873 subref_array_target, expr);
6875 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6876 && !se->data_not_needed)
6878 /* Set the offset. */
6879 gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
6881 else
6883 /* Only the callee knows what the correct offset it, so just set
6884 it to zero here. */
6885 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
6887 desc = parm;
6890 if (!se->direct_byref || se->byref_noassign)
6892 /* Get a pointer to the new descriptor. */
6893 if (se->want_pointer)
6894 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6895 else
6896 se->expr = desc;
6899 gfc_add_block_to_block (&se->pre, &loop.pre);
6900 gfc_add_block_to_block (&se->post, &loop.post);
6902 /* Cleanup the scalarizer. */
6903 gfc_cleanup_loop (&loop);
6906 /* Helper function for gfc_conv_array_parameter if array size needs to be
6907 computed. */
6909 static void
6910 array_parameter_size (tree desc, gfc_expr *expr, tree *size)
6912 tree elem;
6913 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6914 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
6915 else if (expr->rank > 1)
6916 *size = build_call_expr_loc (input_location,
6917 gfor_fndecl_size0, 1,
6918 gfc_build_addr_expr (NULL, desc));
6919 else
6921 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
6922 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
6924 *size = fold_build2_loc (input_location, MINUS_EXPR,
6925 gfc_array_index_type, ubound, lbound);
6926 *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6927 *size, gfc_index_one_node);
6928 *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
6929 *size, gfc_index_zero_node);
6931 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
6932 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6933 *size, fold_convert (gfc_array_index_type, elem));
6936 /* Convert an array for passing as an actual parameter. */
6937 /* TODO: Optimize passing g77 arrays. */
6939 void
6940 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
6941 const gfc_symbol *fsym, const char *proc_name,
6942 tree *size)
6944 tree ptr;
6945 tree desc;
6946 tree tmp = NULL_TREE;
6947 tree stmt;
6948 tree parent = DECL_CONTEXT (current_function_decl);
6949 bool full_array_var;
6950 bool this_array_result;
6951 bool contiguous;
6952 bool no_pack;
6953 bool array_constructor;
6954 bool good_allocatable;
6955 bool ultimate_ptr_comp;
6956 bool ultimate_alloc_comp;
6957 gfc_symbol *sym;
6958 stmtblock_t block;
6959 gfc_ref *ref;
6961 ultimate_ptr_comp = false;
6962 ultimate_alloc_comp = false;
6964 for (ref = expr->ref; ref; ref = ref->next)
6966 if (ref->next == NULL)
6967 break;
6969 if (ref->type == REF_COMPONENT)
6971 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
6972 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
6976 full_array_var = false;
6977 contiguous = false;
6979 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
6980 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
6982 sym = full_array_var ? expr->symtree->n.sym : NULL;
6984 /* The symbol should have an array specification. */
6985 gcc_assert (!sym || sym->as || ref->u.ar.as);
6987 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
6989 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
6990 expr->ts.u.cl->backend_decl = tmp;
6991 se->string_length = tmp;
6994 /* Is this the result of the enclosing procedure? */
6995 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
6996 if (this_array_result
6997 && (sym->backend_decl != current_function_decl)
6998 && (sym->backend_decl != parent))
6999 this_array_result = false;
7001 /* Passing address of the array if it is not pointer or assumed-shape. */
7002 if (full_array_var && g77 && !this_array_result
7003 && sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
7005 tmp = gfc_get_symbol_decl (sym);
7007 if (sym->ts.type == BT_CHARACTER)
7008 se->string_length = sym->ts.u.cl->backend_decl;
7010 if (!sym->attr.pointer
7011 && sym->as
7012 && sym->as->type != AS_ASSUMED_SHAPE
7013 && sym->as->type != AS_DEFERRED
7014 && sym->as->type != AS_ASSUMED_RANK
7015 && !sym->attr.allocatable)
7017 /* Some variables are declared directly, others are declared as
7018 pointers and allocated on the heap. */
7019 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
7020 se->expr = tmp;
7021 else
7022 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
7023 if (size)
7024 array_parameter_size (tmp, expr, size);
7025 return;
7028 if (sym->attr.allocatable)
7030 if (sym->attr.dummy || sym->attr.result)
7032 gfc_conv_expr_descriptor (se, expr);
7033 tmp = se->expr;
7035 if (size)
7036 array_parameter_size (tmp, expr, size);
7037 se->expr = gfc_conv_array_data (tmp);
7038 return;
7042 /* A convenient reduction in scope. */
7043 contiguous = g77 && !this_array_result && contiguous;
7045 /* There is no need to pack and unpack the array, if it is contiguous
7046 and not a deferred- or assumed-shape array, or if it is simply
7047 contiguous. */
7048 no_pack = ((sym && sym->as
7049 && !sym->attr.pointer
7050 && sym->as->type != AS_DEFERRED
7051 && sym->as->type != AS_ASSUMED_RANK
7052 && sym->as->type != AS_ASSUMED_SHAPE)
7054 (ref && ref->u.ar.as
7055 && ref->u.ar.as->type != AS_DEFERRED
7056 && ref->u.ar.as->type != AS_ASSUMED_RANK
7057 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
7059 gfc_is_simply_contiguous (expr, false));
7061 no_pack = contiguous && no_pack;
7063 /* Array constructors are always contiguous and do not need packing. */
7064 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
7066 /* Same is true of contiguous sections from allocatable variables. */
7067 good_allocatable = contiguous
7068 && expr->symtree
7069 && expr->symtree->n.sym->attr.allocatable;
7071 /* Or ultimate allocatable components. */
7072 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
7074 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
7076 gfc_conv_expr_descriptor (se, expr);
7077 if (expr->ts.type == BT_CHARACTER)
7078 se->string_length = expr->ts.u.cl->backend_decl;
7079 if (size)
7080 array_parameter_size (se->expr, expr, size);
7081 se->expr = gfc_conv_array_data (se->expr);
7082 return;
7085 if (this_array_result)
7087 /* Result of the enclosing function. */
7088 gfc_conv_expr_descriptor (se, expr);
7089 if (size)
7090 array_parameter_size (se->expr, expr, size);
7091 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7093 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
7094 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
7095 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
7096 se->expr));
7098 return;
7100 else
7102 /* Every other type of array. */
7103 se->want_pointer = 1;
7104 gfc_conv_expr_descriptor (se, expr);
7105 if (size)
7106 array_parameter_size (build_fold_indirect_ref_loc (input_location,
7107 se->expr),
7108 expr, size);
7111 /* Deallocate the allocatable components of structures that are
7112 not variable. */
7113 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
7114 && expr->ts.u.derived->attr.alloc_comp
7115 && expr->expr_type != EXPR_VARIABLE)
7117 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
7118 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
7120 /* The components shall be deallocated before their containing entity. */
7121 gfc_prepend_expr_to_block (&se->post, tmp);
7124 if (g77 || (fsym && fsym->attr.contiguous
7125 && !gfc_is_simply_contiguous (expr, false)))
7127 tree origptr = NULL_TREE;
7129 desc = se->expr;
7131 /* For contiguous arrays, save the original value of the descriptor. */
7132 if (!g77)
7134 origptr = gfc_create_var (pvoid_type_node, "origptr");
7135 tmp = build_fold_indirect_ref_loc (input_location, desc);
7136 tmp = gfc_conv_array_data (tmp);
7137 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7138 TREE_TYPE (origptr), origptr,
7139 fold_convert (TREE_TYPE (origptr), tmp));
7140 gfc_add_expr_to_block (&se->pre, tmp);
7143 /* Repack the array. */
7144 if (gfc_option.warn_array_temp)
7146 if (fsym)
7147 gfc_warning ("Creating array temporary at %L for argument '%s'",
7148 &expr->where, fsym->name);
7149 else
7150 gfc_warning ("Creating array temporary at %L", &expr->where);
7153 ptr = build_call_expr_loc (input_location,
7154 gfor_fndecl_in_pack, 1, desc);
7156 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7158 tmp = gfc_conv_expr_present (sym);
7159 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
7160 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
7161 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
7164 ptr = gfc_evaluate_now (ptr, &se->pre);
7166 /* Use the packed data for the actual argument, except for contiguous arrays,
7167 where the descriptor's data component is set. */
7168 if (g77)
7169 se->expr = ptr;
7170 else
7172 tmp = build_fold_indirect_ref_loc (input_location, desc);
7173 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
7176 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
7178 char * msg;
7180 if (fsym && proc_name)
7181 asprintf (&msg, "An array temporary was created for argument "
7182 "'%s' of procedure '%s'", fsym->name, proc_name);
7183 else
7184 asprintf (&msg, "An array temporary was created");
7186 tmp = build_fold_indirect_ref_loc (input_location,
7187 desc);
7188 tmp = gfc_conv_array_data (tmp);
7189 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7190 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7192 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7193 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7194 boolean_type_node,
7195 gfc_conv_expr_present (sym), tmp);
7197 gfc_trans_runtime_check (false, true, tmp, &se->pre,
7198 &expr->where, msg);
7199 free (msg);
7202 gfc_start_block (&block);
7204 /* Copy the data back. */
7205 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
7207 tmp = build_call_expr_loc (input_location,
7208 gfor_fndecl_in_unpack, 2, desc, ptr);
7209 gfc_add_expr_to_block (&block, tmp);
7212 /* Free the temporary. */
7213 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
7214 gfc_add_expr_to_block (&block, tmp);
7216 stmt = gfc_finish_block (&block);
7218 gfc_init_block (&block);
7219 /* Only if it was repacked. This code needs to be executed before the
7220 loop cleanup code. */
7221 tmp = build_fold_indirect_ref_loc (input_location,
7222 desc);
7223 tmp = gfc_conv_array_data (tmp);
7224 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7225 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7227 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7228 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7229 boolean_type_node,
7230 gfc_conv_expr_present (sym), tmp);
7232 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
7234 gfc_add_expr_to_block (&block, tmp);
7235 gfc_add_block_to_block (&block, &se->post);
7237 gfc_init_block (&se->post);
7239 /* Reset the descriptor pointer. */
7240 if (!g77)
7242 tmp = build_fold_indirect_ref_loc (input_location, desc);
7243 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
7246 gfc_add_block_to_block (&se->post, &block);
7251 /* Generate code to deallocate an array, if it is allocated. */
7253 tree
7254 gfc_trans_dealloc_allocated (tree descriptor, bool coarray)
7256 tree tmp;
7257 tree var;
7258 stmtblock_t block;
7260 gfc_start_block (&block);
7262 var = gfc_conv_descriptor_data_get (descriptor);
7263 STRIP_NOPS (var);
7265 /* Call array_deallocate with an int * present in the second argument.
7266 Although it is ignored here, it's presence ensures that arrays that
7267 are already deallocated are ignored. */
7268 tmp = gfc_deallocate_with_status (coarray ? descriptor : var, NULL_TREE,
7269 NULL_TREE, NULL_TREE, NULL_TREE, true,
7270 NULL, coarray);
7271 gfc_add_expr_to_block (&block, tmp);
7273 /* Zero the data pointer. */
7274 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7275 var, build_int_cst (TREE_TYPE (var), 0));
7276 gfc_add_expr_to_block (&block, tmp);
7278 return gfc_finish_block (&block);
7282 /* This helper function calculates the size in words of a full array. */
7284 static tree
7285 get_full_array_size (stmtblock_t *block, tree decl, int rank)
7287 tree idx;
7288 tree nelems;
7289 tree tmp;
7290 idx = gfc_rank_cst[rank - 1];
7291 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
7292 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
7293 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7294 nelems, tmp);
7295 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7296 tmp, gfc_index_one_node);
7297 tmp = gfc_evaluate_now (tmp, block);
7299 nelems = gfc_conv_descriptor_stride_get (decl, idx);
7300 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7301 nelems, tmp);
7302 return gfc_evaluate_now (tmp, block);
7306 /* Allocate dest to the same size as src, and copy src -> dest.
7307 If no_malloc is set, only the copy is done. */
7309 static tree
7310 duplicate_allocatable (tree dest, tree src, tree type, int rank,
7311 bool no_malloc)
7313 tree tmp;
7314 tree size;
7315 tree nelems;
7316 tree null_cond;
7317 tree null_data;
7318 stmtblock_t block;
7320 /* If the source is null, set the destination to null. Then,
7321 allocate memory to the destination. */
7322 gfc_init_block (&block);
7324 if (rank == 0)
7326 tmp = null_pointer_node;
7327 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type, dest, tmp);
7328 gfc_add_expr_to_block (&block, tmp);
7329 null_data = gfc_finish_block (&block);
7331 gfc_init_block (&block);
7332 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
7333 if (!no_malloc)
7335 tmp = gfc_call_malloc (&block, type, size);
7336 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7337 dest, fold_convert (type, tmp));
7338 gfc_add_expr_to_block (&block, tmp);
7341 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
7342 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
7343 fold_convert (size_type_node, size));
7345 else
7347 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
7348 null_data = gfc_finish_block (&block);
7350 gfc_init_block (&block);
7351 nelems = get_full_array_size (&block, src, rank);
7352 tmp = fold_convert (gfc_array_index_type,
7353 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
7354 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7355 nelems, tmp);
7356 if (!no_malloc)
7358 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
7359 tmp = gfc_call_malloc (&block, tmp, size);
7360 gfc_conv_descriptor_data_set (&block, dest, tmp);
7363 /* We know the temporary and the value will be the same length,
7364 so can use memcpy. */
7365 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
7366 tmp = build_call_expr_loc (input_location,
7367 tmp, 3, gfc_conv_descriptor_data_get (dest),
7368 gfc_conv_descriptor_data_get (src),
7369 fold_convert (size_type_node, size));
7372 gfc_add_expr_to_block (&block, tmp);
7373 tmp = gfc_finish_block (&block);
7375 /* Null the destination if the source is null; otherwise do
7376 the allocate and copy. */
7377 if (rank == 0)
7378 null_cond = src;
7379 else
7380 null_cond = gfc_conv_descriptor_data_get (src);
7382 null_cond = convert (pvoid_type_node, null_cond);
7383 null_cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7384 null_cond, null_pointer_node);
7385 return build3_v (COND_EXPR, null_cond, tmp, null_data);
7389 /* Allocate dest to the same size as src, and copy data src -> dest. */
7391 tree
7392 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank)
7394 return duplicate_allocatable (dest, src, type, rank, false);
7398 /* Copy data src -> dest. */
7400 tree
7401 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
7403 return duplicate_allocatable (dest, src, type, rank, true);
7407 /* Recursively traverse an object of derived type, generating code to
7408 deallocate, nullify or copy allocatable components. This is the work horse
7409 function for the functions named in this enum. */
7411 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP,
7412 COPY_ONLY_ALLOC_COMP};
7414 static tree
7415 structure_alloc_comps (gfc_symbol * der_type, tree decl,
7416 tree dest, int rank, int purpose)
7418 gfc_component *c;
7419 gfc_loopinfo loop;
7420 stmtblock_t fnblock;
7421 stmtblock_t loopbody;
7422 stmtblock_t tmpblock;
7423 tree decl_type;
7424 tree tmp;
7425 tree comp;
7426 tree dcmp;
7427 tree nelems;
7428 tree index;
7429 tree var;
7430 tree cdecl;
7431 tree ctype;
7432 tree vref, dref;
7433 tree null_cond = NULL_TREE;
7434 bool called_dealloc_with_status;
7436 gfc_init_block (&fnblock);
7438 decl_type = TREE_TYPE (decl);
7440 if ((POINTER_TYPE_P (decl_type) && rank != 0)
7441 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
7442 decl = build_fold_indirect_ref_loc (input_location, decl);
7444 /* Just in case in gets dereferenced. */
7445 decl_type = TREE_TYPE (decl);
7447 /* If this an array of derived types with allocatable components
7448 build a loop and recursively call this function. */
7449 if (TREE_CODE (decl_type) == ARRAY_TYPE
7450 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
7452 tmp = gfc_conv_array_data (decl);
7453 var = build_fold_indirect_ref_loc (input_location,
7454 tmp);
7456 /* Get the number of elements - 1 and set the counter. */
7457 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
7459 /* Use the descriptor for an allocatable array. Since this
7460 is a full array reference, we only need the descriptor
7461 information from dimension = rank. */
7462 tmp = get_full_array_size (&fnblock, decl, rank);
7463 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7464 gfc_array_index_type, tmp,
7465 gfc_index_one_node);
7467 null_cond = gfc_conv_descriptor_data_get (decl);
7468 null_cond = fold_build2_loc (input_location, NE_EXPR,
7469 boolean_type_node, null_cond,
7470 build_int_cst (TREE_TYPE (null_cond), 0));
7472 else
7474 /* Otherwise use the TYPE_DOMAIN information. */
7475 tmp = array_type_nelts (decl_type);
7476 tmp = fold_convert (gfc_array_index_type, tmp);
7479 /* Remember that this is, in fact, the no. of elements - 1. */
7480 nelems = gfc_evaluate_now (tmp, &fnblock);
7481 index = gfc_create_var (gfc_array_index_type, "S");
7483 /* Build the body of the loop. */
7484 gfc_init_block (&loopbody);
7486 vref = gfc_build_array_ref (var, index, NULL);
7488 if (purpose == COPY_ALLOC_COMP)
7490 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
7492 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank);
7493 gfc_add_expr_to_block (&fnblock, tmp);
7495 tmp = build_fold_indirect_ref_loc (input_location,
7496 gfc_conv_array_data (dest));
7497 dref = gfc_build_array_ref (tmp, index, NULL);
7498 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
7500 else if (purpose == COPY_ONLY_ALLOC_COMP)
7502 tmp = build_fold_indirect_ref_loc (input_location,
7503 gfc_conv_array_data (dest));
7504 dref = gfc_build_array_ref (tmp, index, NULL);
7505 tmp = structure_alloc_comps (der_type, vref, dref, rank,
7506 COPY_ALLOC_COMP);
7508 else
7509 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
7511 gfc_add_expr_to_block (&loopbody, tmp);
7513 /* Build the loop and return. */
7514 gfc_init_loopinfo (&loop);
7515 loop.dimen = 1;
7516 loop.from[0] = gfc_index_zero_node;
7517 loop.loopvar[0] = index;
7518 loop.to[0] = nelems;
7519 gfc_trans_scalarizing_loops (&loop, &loopbody);
7520 gfc_add_block_to_block (&fnblock, &loop.pre);
7522 tmp = gfc_finish_block (&fnblock);
7523 if (null_cond != NULL_TREE)
7524 tmp = build3_v (COND_EXPR, null_cond, tmp,
7525 build_empty_stmt (input_location));
7527 return tmp;
7530 /* Otherwise, act on the components or recursively call self to
7531 act on a chain of components. */
7532 for (c = der_type->components; c; c = c->next)
7534 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
7535 || c->ts.type == BT_CLASS)
7536 && c->ts.u.derived->attr.alloc_comp;
7537 cdecl = c->backend_decl;
7538 ctype = TREE_TYPE (cdecl);
7540 switch (purpose)
7542 case DEALLOCATE_ALLOC_COMP:
7544 /* gfc_deallocate_scalar_with_status calls gfc_deallocate_alloc_comp
7545 (i.e. this function) so generate all the calls and suppress the
7546 recursion from here, if necessary. */
7547 called_dealloc_with_status = false;
7548 gfc_init_block (&tmpblock);
7550 if (c->attr.allocatable && (c->attr.dimension || c->attr.codimension)
7551 && !c->attr.proc_pointer)
7553 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7554 decl, cdecl, NULL_TREE);
7555 tmp = gfc_trans_dealloc_allocated (comp, c->attr.codimension);
7556 gfc_add_expr_to_block (&tmpblock, tmp);
7558 else if (c->attr.allocatable)
7560 /* Allocatable scalar components. */
7561 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7562 decl, cdecl, NULL_TREE);
7564 tmp = gfc_deallocate_scalar_with_status (comp, NULL, true, NULL,
7565 c->ts);
7566 gfc_add_expr_to_block (&tmpblock, tmp);
7567 called_dealloc_with_status = true;
7569 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7570 void_type_node, comp,
7571 build_int_cst (TREE_TYPE (comp), 0));
7572 gfc_add_expr_to_block (&tmpblock, tmp);
7574 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7576 /* Allocatable CLASS components. */
7577 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7578 decl, cdecl, NULL_TREE);
7580 /* Add reference to '_data' component. */
7581 tmp = CLASS_DATA (c)->backend_decl;
7582 comp = fold_build3_loc (input_location, COMPONENT_REF,
7583 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
7585 if (GFC_DESCRIPTOR_TYPE_P(TREE_TYPE (comp)))
7586 tmp = gfc_trans_dealloc_allocated (comp,
7587 CLASS_DATA (c)->attr.codimension);
7588 else
7590 tmp = gfc_deallocate_scalar_with_status (comp, NULL_TREE, true, NULL,
7591 CLASS_DATA (c)->ts);
7592 gfc_add_expr_to_block (&tmpblock, tmp);
7593 called_dealloc_with_status = true;
7595 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7596 void_type_node, comp,
7597 build_int_cst (TREE_TYPE (comp), 0));
7599 gfc_add_expr_to_block (&tmpblock, tmp);
7602 if (cmp_has_alloc_comps
7603 && !c->attr.pointer
7604 && !called_dealloc_with_status)
7606 /* Do not deallocate the components of ultimate pointer
7607 components or iteratively call self if call has been made
7608 to gfc_trans_dealloc_allocated */
7609 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7610 decl, cdecl, NULL_TREE);
7611 rank = c->as ? c->as->rank : 0;
7612 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
7613 rank, purpose);
7614 gfc_add_expr_to_block (&fnblock, tmp);
7617 /* Now add the deallocation of this component. */
7618 gfc_add_block_to_block (&fnblock, &tmpblock);
7619 break;
7621 case NULLIFY_ALLOC_COMP:
7622 if (c->attr.pointer)
7623 continue;
7624 else if (c->attr.allocatable
7625 && (c->attr.dimension|| c->attr.codimension))
7627 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7628 decl, cdecl, NULL_TREE);
7629 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
7631 else if (c->attr.allocatable)
7633 /* Allocatable scalar components. */
7634 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7635 decl, cdecl, NULL_TREE);
7636 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7637 void_type_node, comp,
7638 build_int_cst (TREE_TYPE (comp), 0));
7639 gfc_add_expr_to_block (&fnblock, tmp);
7641 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7643 /* Allocatable CLASS components. */
7644 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7645 decl, cdecl, NULL_TREE);
7646 /* Add reference to '_data' component. */
7647 tmp = CLASS_DATA (c)->backend_decl;
7648 comp = fold_build3_loc (input_location, COMPONENT_REF,
7649 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
7650 if (GFC_DESCRIPTOR_TYPE_P(TREE_TYPE (comp)))
7651 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
7652 else
7654 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7655 void_type_node, comp,
7656 build_int_cst (TREE_TYPE (comp), 0));
7657 gfc_add_expr_to_block (&fnblock, tmp);
7660 else if (cmp_has_alloc_comps)
7662 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7663 decl, cdecl, NULL_TREE);
7664 rank = c->as ? c->as->rank : 0;
7665 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
7666 rank, purpose);
7667 gfc_add_expr_to_block (&fnblock, tmp);
7669 break;
7671 case COPY_ALLOC_COMP:
7672 if (c->attr.pointer)
7673 continue;
7675 /* We need source and destination components. */
7676 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
7677 cdecl, NULL_TREE);
7678 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
7679 cdecl, NULL_TREE);
7680 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
7682 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7684 tree ftn_tree;
7685 tree size;
7686 tree dst_data;
7687 tree src_data;
7688 tree null_data;
7690 dst_data = gfc_class_data_get (dcmp);
7691 src_data = gfc_class_data_get (comp);
7692 size = fold_convert (size_type_node, gfc_vtable_size_get (comp));
7694 if (CLASS_DATA (c)->attr.dimension)
7696 nelems = gfc_conv_descriptor_size (src_data,
7697 CLASS_DATA (c)->as->rank);
7698 src_data = gfc_conv_descriptor_data_get (src_data);
7699 dst_data = gfc_conv_descriptor_data_get (dst_data);
7701 else
7702 nelems = build_int_cst (size_type_node, 1);
7704 gfc_init_block (&tmpblock);
7706 /* We need to use CALLOC as _copy might try to free allocatable
7707 components of the destination. */
7708 ftn_tree = builtin_decl_explicit (BUILT_IN_CALLOC);
7709 tmp = build_call_expr_loc (input_location, ftn_tree, 2, nelems,
7710 size);
7711 gfc_add_modify (&tmpblock, dst_data,
7712 fold_convert (TREE_TYPE (dst_data), tmp));
7714 tmp = gfc_copy_class_to_class (comp, dcmp, nelems);
7715 gfc_add_expr_to_block (&tmpblock, tmp);
7716 tmp = gfc_finish_block (&tmpblock);
7718 gfc_init_block (&tmpblock);
7719 gfc_add_modify (&tmpblock, dst_data,
7720 fold_convert (TREE_TYPE (dst_data),
7721 null_pointer_node));
7722 null_data = gfc_finish_block (&tmpblock);
7724 null_cond = fold_build2_loc (input_location, NE_EXPR,
7725 boolean_type_node, src_data,
7726 null_pointer_node);
7728 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
7729 tmp, null_data));
7730 continue;
7733 if (c->attr.allocatable && !c->attr.proc_pointer
7734 && !cmp_has_alloc_comps)
7736 rank = c->as ? c->as->rank : 0;
7737 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank);
7738 gfc_add_expr_to_block (&fnblock, tmp);
7741 if (cmp_has_alloc_comps)
7743 rank = c->as ? c->as->rank : 0;
7744 tmp = fold_convert (TREE_TYPE (dcmp), comp);
7745 gfc_add_modify (&fnblock, dcmp, tmp);
7746 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
7747 rank, purpose);
7748 gfc_add_expr_to_block (&fnblock, tmp);
7750 break;
7752 default:
7753 gcc_unreachable ();
7754 break;
7758 return gfc_finish_block (&fnblock);
7761 /* Recursively traverse an object of derived type, generating code to
7762 nullify allocatable components. */
7764 tree
7765 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
7767 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
7768 NULLIFY_ALLOC_COMP);
7772 /* Recursively traverse an object of derived type, generating code to
7773 deallocate allocatable components. */
7775 tree
7776 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
7778 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
7779 DEALLOCATE_ALLOC_COMP);
7783 /* Recursively traverse an object of derived type, generating code to
7784 copy it and its allocatable components. */
7786 tree
7787 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
7789 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
7793 /* Recursively traverse an object of derived type, generating code to
7794 copy only its allocatable components. */
7796 tree
7797 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
7799 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ONLY_ALLOC_COMP);
7803 /* Returns the value of LBOUND for an expression. This could be broken out
7804 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
7805 called by gfc_alloc_allocatable_for_assignment. */
7806 static tree
7807 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
7809 tree lbound;
7810 tree ubound;
7811 tree stride;
7812 tree cond, cond1, cond3, cond4;
7813 tree tmp;
7814 gfc_ref *ref;
7816 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
7818 tmp = gfc_rank_cst[dim];
7819 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
7820 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
7821 stride = gfc_conv_descriptor_stride_get (desc, tmp);
7822 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
7823 ubound, lbound);
7824 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
7825 stride, gfc_index_zero_node);
7826 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7827 boolean_type_node, cond3, cond1);
7828 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
7829 stride, gfc_index_zero_node);
7830 if (assumed_size)
7831 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
7832 tmp, build_int_cst (gfc_array_index_type,
7833 expr->rank - 1));
7834 else
7835 cond = boolean_false_node;
7837 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
7838 boolean_type_node, cond3, cond4);
7839 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
7840 boolean_type_node, cond, cond1);
7842 return fold_build3_loc (input_location, COND_EXPR,
7843 gfc_array_index_type, cond,
7844 lbound, gfc_index_one_node);
7847 if (expr->expr_type == EXPR_FUNCTION)
7849 /* A conversion function, so use the argument. */
7850 gcc_assert (expr->value.function.isym
7851 && expr->value.function.isym->conversion);
7852 expr = expr->value.function.actual->expr;
7855 if (expr->expr_type == EXPR_VARIABLE)
7857 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
7858 for (ref = expr->ref; ref; ref = ref->next)
7860 if (ref->type == REF_COMPONENT
7861 && ref->u.c.component->as
7862 && ref->next
7863 && ref->next->u.ar.type == AR_FULL)
7864 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
7866 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
7869 return gfc_index_one_node;
7873 /* Returns true if an expression represents an lhs that can be reallocated
7874 on assignment. */
7876 bool
7877 gfc_is_reallocatable_lhs (gfc_expr *expr)
7879 gfc_ref * ref;
7881 if (!expr->ref)
7882 return false;
7884 /* An allocatable variable. */
7885 if (expr->symtree->n.sym->attr.allocatable
7886 && expr->ref
7887 && expr->ref->type == REF_ARRAY
7888 && expr->ref->u.ar.type == AR_FULL)
7889 return true;
7891 /* All that can be left are allocatable components. */
7892 if ((expr->symtree->n.sym->ts.type != BT_DERIVED
7893 && expr->symtree->n.sym->ts.type != BT_CLASS)
7894 || !expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
7895 return false;
7897 /* Find a component ref followed by an array reference. */
7898 for (ref = expr->ref; ref; ref = ref->next)
7899 if (ref->next
7900 && ref->type == REF_COMPONENT
7901 && ref->next->type == REF_ARRAY
7902 && !ref->next->next)
7903 break;
7905 if (!ref)
7906 return false;
7908 /* Return true if valid reallocatable lhs. */
7909 if (ref->u.c.component->attr.allocatable
7910 && ref->next->u.ar.type == AR_FULL)
7911 return true;
7913 return false;
7917 /* Allocate the lhs of an assignment to an allocatable array, otherwise
7918 reallocate it. */
7920 tree
7921 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
7922 gfc_expr *expr1,
7923 gfc_expr *expr2)
7925 stmtblock_t realloc_block;
7926 stmtblock_t alloc_block;
7927 stmtblock_t fblock;
7928 gfc_ss *rss;
7929 gfc_ss *lss;
7930 gfc_array_info *linfo;
7931 tree realloc_expr;
7932 tree alloc_expr;
7933 tree size1;
7934 tree size2;
7935 tree array1;
7936 tree cond;
7937 tree tmp;
7938 tree tmp2;
7939 tree lbound;
7940 tree ubound;
7941 tree desc;
7942 tree old_desc;
7943 tree desc2;
7944 tree offset;
7945 tree jump_label1;
7946 tree jump_label2;
7947 tree neq_size;
7948 tree lbd;
7949 int n;
7950 int dim;
7951 gfc_array_spec * as;
7953 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
7954 Find the lhs expression in the loop chain and set expr1 and
7955 expr2 accordingly. */
7956 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
7958 expr2 = expr1;
7959 /* Find the ss for the lhs. */
7960 lss = loop->ss;
7961 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
7962 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
7963 break;
7964 if (lss == gfc_ss_terminator)
7965 return NULL_TREE;
7966 expr1 = lss->info->expr;
7969 /* Bail out if this is not a valid allocate on assignment. */
7970 if (!gfc_is_reallocatable_lhs (expr1)
7971 || (expr2 && !expr2->rank))
7972 return NULL_TREE;
7974 /* Find the ss for the lhs. */
7975 lss = loop->ss;
7976 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
7977 if (lss->info->expr == expr1)
7978 break;
7980 if (lss == gfc_ss_terminator)
7981 return NULL_TREE;
7983 linfo = &lss->info->data.array;
7985 /* Find an ss for the rhs. For operator expressions, we see the
7986 ss's for the operands. Any one of these will do. */
7987 rss = loop->ss;
7988 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
7989 if (rss->info->expr != expr1 && rss != loop->temp_ss)
7990 break;
7992 if (expr2 && rss == gfc_ss_terminator)
7993 return NULL_TREE;
7995 gfc_start_block (&fblock);
7997 /* Since the lhs is allocatable, this must be a descriptor type.
7998 Get the data and array size. */
7999 desc = linfo->descriptor;
8000 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
8001 array1 = gfc_conv_descriptor_data_get (desc);
8003 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
8004 deallocated if expr is an array of different shape or any of the
8005 corresponding length type parameter values of variable and expr
8006 differ." This assures F95 compatibility. */
8007 jump_label1 = gfc_build_label_decl (NULL_TREE);
8008 jump_label2 = gfc_build_label_decl (NULL_TREE);
8010 /* Allocate if data is NULL. */
8011 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8012 array1, build_int_cst (TREE_TYPE (array1), 0));
8013 tmp = build3_v (COND_EXPR, cond,
8014 build1_v (GOTO_EXPR, jump_label1),
8015 build_empty_stmt (input_location));
8016 gfc_add_expr_to_block (&fblock, tmp);
8018 /* Get arrayspec if expr is a full array. */
8019 if (expr2 && expr2->expr_type == EXPR_FUNCTION
8020 && expr2->value.function.isym
8021 && expr2->value.function.isym->conversion)
8023 /* For conversion functions, take the arg. */
8024 gfc_expr *arg = expr2->value.function.actual->expr;
8025 as = gfc_get_full_arrayspec_from_expr (arg);
8027 else if (expr2)
8028 as = gfc_get_full_arrayspec_from_expr (expr2);
8029 else
8030 as = NULL;
8032 /* If the lhs shape is not the same as the rhs jump to setting the
8033 bounds and doing the reallocation....... */
8034 for (n = 0; n < expr1->rank; n++)
8036 /* Check the shape. */
8037 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
8038 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
8039 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8040 gfc_array_index_type,
8041 loop->to[n], loop->from[n]);
8042 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8043 gfc_array_index_type,
8044 tmp, lbound);
8045 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8046 gfc_array_index_type,
8047 tmp, ubound);
8048 cond = fold_build2_loc (input_location, NE_EXPR,
8049 boolean_type_node,
8050 tmp, gfc_index_zero_node);
8051 tmp = build3_v (COND_EXPR, cond,
8052 build1_v (GOTO_EXPR, jump_label1),
8053 build_empty_stmt (input_location));
8054 gfc_add_expr_to_block (&fblock, tmp);
8057 /* ....else jump past the (re)alloc code. */
8058 tmp = build1_v (GOTO_EXPR, jump_label2);
8059 gfc_add_expr_to_block (&fblock, tmp);
8061 /* Add the label to start automatic (re)allocation. */
8062 tmp = build1_v (LABEL_EXPR, jump_label1);
8063 gfc_add_expr_to_block (&fblock, tmp);
8065 size1 = gfc_conv_descriptor_size (desc, expr1->rank);
8067 /* Get the rhs size. Fix both sizes. */
8068 if (expr2)
8069 desc2 = rss->info->data.array.descriptor;
8070 else
8071 desc2 = NULL_TREE;
8072 size2 = gfc_index_one_node;
8073 for (n = 0; n < expr2->rank; n++)
8075 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8076 gfc_array_index_type,
8077 loop->to[n], loop->from[n]);
8078 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8079 gfc_array_index_type,
8080 tmp, gfc_index_one_node);
8081 size2 = fold_build2_loc (input_location, MULT_EXPR,
8082 gfc_array_index_type,
8083 tmp, size2);
8086 size1 = gfc_evaluate_now (size1, &fblock);
8087 size2 = gfc_evaluate_now (size2, &fblock);
8089 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
8090 size1, size2);
8091 neq_size = gfc_evaluate_now (cond, &fblock);
8093 /* Deallocation of allocatable components will have to occur on
8094 reallocation. Fix the old descriptor now. */
8095 if ((expr1->ts.type == BT_DERIVED)
8096 && expr1->ts.u.derived->attr.alloc_comp)
8097 old_desc = gfc_evaluate_now (desc, &fblock);
8098 else
8099 old_desc = NULL_TREE;
8101 /* Now modify the lhs descriptor and the associated scalarizer
8102 variables. F2003 7.4.1.3: "If variable is or becomes an
8103 unallocated allocatable variable, then it is allocated with each
8104 deferred type parameter equal to the corresponding type parameters
8105 of expr , with the shape of expr , and with each lower bound equal
8106 to the corresponding element of LBOUND(expr)."
8107 Reuse size1 to keep a dimension-by-dimension track of the
8108 stride of the new array. */
8109 size1 = gfc_index_one_node;
8110 offset = gfc_index_zero_node;
8112 for (n = 0; n < expr2->rank; n++)
8114 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8115 gfc_array_index_type,
8116 loop->to[n], loop->from[n]);
8117 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8118 gfc_array_index_type,
8119 tmp, gfc_index_one_node);
8121 lbound = gfc_index_one_node;
8122 ubound = tmp;
8124 if (as)
8126 lbd = get_std_lbound (expr2, desc2, n,
8127 as->type == AS_ASSUMED_SIZE);
8128 ubound = fold_build2_loc (input_location,
8129 MINUS_EXPR,
8130 gfc_array_index_type,
8131 ubound, lbound);
8132 ubound = fold_build2_loc (input_location,
8133 PLUS_EXPR,
8134 gfc_array_index_type,
8135 ubound, lbd);
8136 lbound = lbd;
8139 gfc_conv_descriptor_lbound_set (&fblock, desc,
8140 gfc_rank_cst[n],
8141 lbound);
8142 gfc_conv_descriptor_ubound_set (&fblock, desc,
8143 gfc_rank_cst[n],
8144 ubound);
8145 gfc_conv_descriptor_stride_set (&fblock, desc,
8146 gfc_rank_cst[n],
8147 size1);
8148 lbound = gfc_conv_descriptor_lbound_get (desc,
8149 gfc_rank_cst[n]);
8150 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
8151 gfc_array_index_type,
8152 lbound, size1);
8153 offset = fold_build2_loc (input_location, MINUS_EXPR,
8154 gfc_array_index_type,
8155 offset, tmp2);
8156 size1 = fold_build2_loc (input_location, MULT_EXPR,
8157 gfc_array_index_type,
8158 tmp, size1);
8161 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
8162 the array offset is saved and the info.offset is used for a
8163 running offset. Use the saved_offset instead. */
8164 tmp = gfc_conv_descriptor_offset (desc);
8165 gfc_add_modify (&fblock, tmp, offset);
8166 if (linfo->saved_offset
8167 && TREE_CODE (linfo->saved_offset) == VAR_DECL)
8168 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
8170 /* Now set the deltas for the lhs. */
8171 for (n = 0; n < expr1->rank; n++)
8173 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
8174 dim = lss->dim[n];
8175 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8176 gfc_array_index_type, tmp,
8177 loop->from[dim]);
8178 if (linfo->delta[dim]
8179 && TREE_CODE (linfo->delta[dim]) == VAR_DECL)
8180 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
8183 /* Get the new lhs size in bytes. */
8184 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
8186 tmp = expr2->ts.u.cl->backend_decl;
8187 gcc_assert (expr1->ts.u.cl->backend_decl);
8188 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
8189 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
8191 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
8193 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
8194 tmp = fold_build2_loc (input_location, MULT_EXPR,
8195 gfc_array_index_type, tmp,
8196 expr1->ts.u.cl->backend_decl);
8198 else
8199 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
8200 tmp = fold_convert (gfc_array_index_type, tmp);
8201 size2 = fold_build2_loc (input_location, MULT_EXPR,
8202 gfc_array_index_type,
8203 tmp, size2);
8204 size2 = fold_convert (size_type_node, size2);
8205 size2 = gfc_evaluate_now (size2, &fblock);
8207 /* Realloc expression. Note that the scalarizer uses desc.data
8208 in the array reference - (*desc.data)[<element>]. */
8209 gfc_init_block (&realloc_block);
8211 if ((expr1->ts.type == BT_DERIVED)
8212 && expr1->ts.u.derived->attr.alloc_comp)
8214 tmp = gfc_deallocate_alloc_comp (expr1->ts.u.derived, old_desc,
8215 expr1->rank);
8216 gfc_add_expr_to_block (&realloc_block, tmp);
8219 tmp = build_call_expr_loc (input_location,
8220 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
8221 fold_convert (pvoid_type_node, array1),
8222 size2);
8223 gfc_conv_descriptor_data_set (&realloc_block,
8224 desc, tmp);
8226 if ((expr1->ts.type == BT_DERIVED)
8227 && expr1->ts.u.derived->attr.alloc_comp)
8229 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
8230 expr1->rank);
8231 gfc_add_expr_to_block (&realloc_block, tmp);
8234 realloc_expr = gfc_finish_block (&realloc_block);
8236 /* Only reallocate if sizes are different. */
8237 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
8238 build_empty_stmt (input_location));
8239 realloc_expr = tmp;
8242 /* Malloc expression. */
8243 gfc_init_block (&alloc_block);
8244 tmp = build_call_expr_loc (input_location,
8245 builtin_decl_explicit (BUILT_IN_MALLOC),
8246 1, size2);
8247 gfc_conv_descriptor_data_set (&alloc_block,
8248 desc, tmp);
8249 tmp = gfc_conv_descriptor_dtype (desc);
8250 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
8251 if ((expr1->ts.type == BT_DERIVED)
8252 && expr1->ts.u.derived->attr.alloc_comp)
8254 tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, desc,
8255 expr1->rank);
8256 gfc_add_expr_to_block (&alloc_block, tmp);
8258 alloc_expr = gfc_finish_block (&alloc_block);
8260 /* Malloc if not allocated; realloc otherwise. */
8261 tmp = build_int_cst (TREE_TYPE (array1), 0);
8262 cond = fold_build2_loc (input_location, EQ_EXPR,
8263 boolean_type_node,
8264 array1, tmp);
8265 tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
8266 gfc_add_expr_to_block (&fblock, tmp);
8268 /* Make sure that the scalarizer data pointer is updated. */
8269 if (linfo->data
8270 && TREE_CODE (linfo->data) == VAR_DECL)
8272 tmp = gfc_conv_descriptor_data_get (desc);
8273 gfc_add_modify (&fblock, linfo->data, tmp);
8276 /* Add the exit label. */
8277 tmp = build1_v (LABEL_EXPR, jump_label2);
8278 gfc_add_expr_to_block (&fblock, tmp);
8280 return gfc_finish_block (&fblock);
8284 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
8285 Do likewise, recursively if necessary, with the allocatable components of
8286 derived types. */
8288 void
8289 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
8291 tree type;
8292 tree tmp;
8293 tree descriptor;
8294 stmtblock_t init;
8295 stmtblock_t cleanup;
8296 locus loc;
8297 int rank;
8298 bool sym_has_alloc_comp;
8300 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
8301 || sym->ts.type == BT_CLASS)
8302 && sym->ts.u.derived->attr.alloc_comp;
8304 /* Make sure the frontend gets these right. */
8305 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
8306 fatal_error ("Possible front-end bug: Deferred array size without pointer, "
8307 "allocatable attribute or derived type without allocatable "
8308 "components.");
8310 gfc_save_backend_locus (&loc);
8311 gfc_set_backend_locus (&sym->declared_at);
8312 gfc_init_block (&init);
8314 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
8315 || TREE_CODE (sym->backend_decl) == PARM_DECL);
8317 if (sym->ts.type == BT_CHARACTER
8318 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
8320 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
8321 gfc_trans_vla_type_sizes (sym, &init);
8324 /* Dummy, use associated and result variables don't need anything special. */
8325 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
8327 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
8328 gfc_restore_backend_locus (&loc);
8329 return;
8332 descriptor = sym->backend_decl;
8334 /* Although static, derived types with default initializers and
8335 allocatable components must not be nulled wholesale; instead they
8336 are treated component by component. */
8337 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
8339 /* SAVEd variables are not freed on exit. */
8340 gfc_trans_static_array_pointer (sym);
8342 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
8343 gfc_restore_backend_locus (&loc);
8344 return;
8347 /* Get the descriptor type. */
8348 type = TREE_TYPE (sym->backend_decl);
8350 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
8352 if (!sym->attr.save
8353 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
8355 if (sym->value == NULL
8356 || !gfc_has_default_initializer (sym->ts.u.derived))
8358 rank = sym->as ? sym->as->rank : 0;
8359 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
8360 descriptor, rank);
8361 gfc_add_expr_to_block (&init, tmp);
8363 else
8364 gfc_init_default_dt (sym, &init, false);
8367 else if (!GFC_DESCRIPTOR_TYPE_P (type))
8369 /* If the backend_decl is not a descriptor, we must have a pointer
8370 to one. */
8371 descriptor = build_fold_indirect_ref_loc (input_location,
8372 sym->backend_decl);
8373 type = TREE_TYPE (descriptor);
8376 /* NULLIFY the data pointer. */
8377 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
8378 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
8380 gfc_restore_backend_locus (&loc);
8381 gfc_init_block (&cleanup);
8383 /* Allocatable arrays need to be freed when they go out of scope.
8384 The allocatable components of pointers must not be touched. */
8385 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
8386 && !sym->attr.pointer && !sym->attr.save)
8388 int rank;
8389 rank = sym->as ? sym->as->rank : 0;
8390 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
8391 gfc_add_expr_to_block (&cleanup, tmp);
8394 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
8395 && !sym->attr.save && !sym->attr.result)
8397 tmp = gfc_trans_dealloc_allocated (sym->backend_decl,
8398 sym->attr.codimension);
8399 gfc_add_expr_to_block (&cleanup, tmp);
8402 gfc_add_init_cleanup (block, gfc_finish_block (&init),
8403 gfc_finish_block (&cleanup));
8406 /************ Expression Walking Functions ******************/
8408 /* Walk a variable reference.
8410 Possible extension - multiple component subscripts.
8411 x(:,:) = foo%a(:)%b(:)
8412 Transforms to
8413 forall (i=..., j=...)
8414 x(i,j) = foo%a(j)%b(i)
8415 end forall
8416 This adds a fair amount of complexity because you need to deal with more
8417 than one ref. Maybe handle in a similar manner to vector subscripts.
8418 Maybe not worth the effort. */
8421 static gfc_ss *
8422 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
8424 gfc_ref *ref;
8426 for (ref = expr->ref; ref; ref = ref->next)
8427 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
8428 break;
8430 return gfc_walk_array_ref (ss, expr, ref);
8434 gfc_ss *
8435 gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
8437 gfc_array_ref *ar;
8438 gfc_ss *newss;
8439 int n;
8441 for (; ref; ref = ref->next)
8443 if (ref->type == REF_SUBSTRING)
8445 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
8446 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
8449 /* We're only interested in array sections from now on. */
8450 if (ref->type != REF_ARRAY)
8451 continue;
8453 ar = &ref->u.ar;
8455 switch (ar->type)
8457 case AR_ELEMENT:
8458 for (n = ar->dimen - 1; n >= 0; n--)
8459 ss = gfc_get_scalar_ss (ss, ar->start[n]);
8460 break;
8462 case AR_FULL:
8463 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
8464 newss->info->data.array.ref = ref;
8466 /* Make sure array is the same as array(:,:), this way
8467 we don't need to special case all the time. */
8468 ar->dimen = ar->as->rank;
8469 for (n = 0; n < ar->dimen; n++)
8471 ar->dimen_type[n] = DIMEN_RANGE;
8473 gcc_assert (ar->start[n] == NULL);
8474 gcc_assert (ar->end[n] == NULL);
8475 gcc_assert (ar->stride[n] == NULL);
8477 ss = newss;
8478 break;
8480 case AR_SECTION:
8481 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
8482 newss->info->data.array.ref = ref;
8484 /* We add SS chains for all the subscripts in the section. */
8485 for (n = 0; n < ar->dimen; n++)
8487 gfc_ss *indexss;
8489 switch (ar->dimen_type[n])
8491 case DIMEN_ELEMENT:
8492 /* Add SS for elemental (scalar) subscripts. */
8493 gcc_assert (ar->start[n]);
8494 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
8495 indexss->loop_chain = gfc_ss_terminator;
8496 newss->info->data.array.subscript[n] = indexss;
8497 break;
8499 case DIMEN_RANGE:
8500 /* We don't add anything for sections, just remember this
8501 dimension for later. */
8502 newss->dim[newss->dimen] = n;
8503 newss->dimen++;
8504 break;
8506 case DIMEN_VECTOR:
8507 /* Create a GFC_SS_VECTOR index in which we can store
8508 the vector's descriptor. */
8509 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
8510 1, GFC_SS_VECTOR);
8511 indexss->loop_chain = gfc_ss_terminator;
8512 newss->info->data.array.subscript[n] = indexss;
8513 newss->dim[newss->dimen] = n;
8514 newss->dimen++;
8515 break;
8517 default:
8518 /* We should know what sort of section it is by now. */
8519 gcc_unreachable ();
8522 /* We should have at least one non-elemental dimension,
8523 unless we are creating a descriptor for a (scalar) coarray. */
8524 gcc_assert (newss->dimen > 0
8525 || newss->info->data.array.ref->u.ar.as->corank > 0);
8526 ss = newss;
8527 break;
8529 default:
8530 /* We should know what sort of section it is by now. */
8531 gcc_unreachable ();
8535 return ss;
8539 /* Walk an expression operator. If only one operand of a binary expression is
8540 scalar, we must also add the scalar term to the SS chain. */
8542 static gfc_ss *
8543 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
8545 gfc_ss *head;
8546 gfc_ss *head2;
8548 head = gfc_walk_subexpr (ss, expr->value.op.op1);
8549 if (expr->value.op.op2 == NULL)
8550 head2 = head;
8551 else
8552 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
8554 /* All operands are scalar. Pass back and let the caller deal with it. */
8555 if (head2 == ss)
8556 return head2;
8558 /* All operands require scalarization. */
8559 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
8560 return head2;
8562 /* One of the operands needs scalarization, the other is scalar.
8563 Create a gfc_ss for the scalar expression. */
8564 if (head == ss)
8566 /* First operand is scalar. We build the chain in reverse order, so
8567 add the scalar SS after the second operand. */
8568 head = head2;
8569 while (head && head->next != ss)
8570 head = head->next;
8571 /* Check we haven't somehow broken the chain. */
8572 gcc_assert (head);
8573 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
8575 else /* head2 == head */
8577 gcc_assert (head2 == head);
8578 /* Second operand is scalar. */
8579 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
8582 return head2;
8586 /* Reverse a SS chain. */
8588 gfc_ss *
8589 gfc_reverse_ss (gfc_ss * ss)
8591 gfc_ss *next;
8592 gfc_ss *head;
8594 gcc_assert (ss != NULL);
8596 head = gfc_ss_terminator;
8597 while (ss != gfc_ss_terminator)
8599 next = ss->next;
8600 /* Check we didn't somehow break the chain. */
8601 gcc_assert (next != NULL);
8602 ss->next = head;
8603 head = ss;
8604 ss = next;
8607 return (head);
8611 /* Given an expression referring to a procedure, return the symbol of its
8612 interface. We can't get the procedure symbol directly as we have to handle
8613 the case of (deferred) type-bound procedures. */
8615 gfc_symbol *
8616 gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
8618 gfc_symbol *sym;
8619 gfc_ref *ref;
8621 if (procedure_ref == NULL)
8622 return NULL;
8624 /* Normal procedure case. */
8625 sym = procedure_ref->symtree->n.sym;
8627 /* Typebound procedure case. */
8628 for (ref = procedure_ref->ref; ref; ref = ref->next)
8630 if (ref->type == REF_COMPONENT
8631 && ref->u.c.component->attr.proc_pointer)
8632 sym = ref->u.c.component->ts.interface;
8633 else
8634 sym = NULL;
8637 return sym;
8641 /* Walk the arguments of an elemental function.
8642 PROC_EXPR is used to check whether an argument is permitted to be absent. If
8643 it is NULL, we don't do the check and the argument is assumed to be present.
8646 gfc_ss *
8647 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
8648 gfc_symbol *proc_ifc, gfc_ss_type type)
8650 gfc_formal_arglist *dummy_arg;
8651 int scalar;
8652 gfc_ss *head;
8653 gfc_ss *tail;
8654 gfc_ss *newss;
8656 head = gfc_ss_terminator;
8657 tail = NULL;
8659 if (proc_ifc)
8660 dummy_arg = gfc_sym_get_dummy_args (proc_ifc);
8661 else
8662 dummy_arg = NULL;
8664 scalar = 1;
8665 for (; arg; arg = arg->next)
8667 if (!arg->expr || arg->expr->expr_type == EXPR_NULL)
8668 continue;
8670 newss = gfc_walk_subexpr (head, arg->expr);
8671 if (newss == head)
8673 /* Scalar argument. */
8674 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
8675 newss = gfc_get_scalar_ss (head, arg->expr);
8676 newss->info->type = type;
8679 else
8680 scalar = 0;
8682 if (dummy_arg != NULL
8683 && dummy_arg->sym->attr.optional
8684 && arg->expr->expr_type == EXPR_VARIABLE
8685 && (gfc_expr_attr (arg->expr).optional
8686 || gfc_expr_attr (arg->expr).allocatable
8687 || gfc_expr_attr (arg->expr).pointer))
8688 newss->info->can_be_null_ref = true;
8690 head = newss;
8691 if (!tail)
8693 tail = head;
8694 while (tail->next != gfc_ss_terminator)
8695 tail = tail->next;
8698 if (dummy_arg != NULL)
8699 dummy_arg = dummy_arg->next;
8702 if (scalar)
8704 /* If all the arguments are scalar we don't need the argument SS. */
8705 gfc_free_ss_chain (head);
8706 /* Pass it back. */
8707 return ss;
8710 /* Add it onto the existing chain. */
8711 tail->next = ss;
8712 return head;
8716 /* Walk a function call. Scalar functions are passed back, and taken out of
8717 scalarization loops. For elemental functions we walk their arguments.
8718 The result of functions returning arrays is stored in a temporary outside
8719 the loop, so that the function is only called once. Hence we do not need
8720 to walk their arguments. */
8722 static gfc_ss *
8723 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
8725 gfc_intrinsic_sym *isym;
8726 gfc_symbol *sym;
8727 gfc_component *comp = NULL;
8729 isym = expr->value.function.isym;
8731 /* Handle intrinsic functions separately. */
8732 if (isym)
8733 return gfc_walk_intrinsic_function (ss, expr, isym);
8735 sym = expr->value.function.esym;
8736 if (!sym)
8737 sym = expr->symtree->n.sym;
8739 /* A function that returns arrays. */
8740 comp = gfc_get_proc_ptr_comp (expr);
8741 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
8742 || (comp && comp->attr.dimension))
8743 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
8745 /* Walk the parameters of an elemental function. For now we always pass
8746 by reference. */
8747 if (sym->attr.elemental || (comp && comp->attr.elemental))
8748 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
8749 gfc_get_proc_ifc_for_expr (expr),
8750 GFC_SS_REFERENCE);
8752 /* Scalar functions are OK as these are evaluated outside the scalarization
8753 loop. Pass back and let the caller deal with it. */
8754 return ss;
8758 /* An array temporary is constructed for array constructors. */
8760 static gfc_ss *
8761 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
8763 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
8767 /* Walk an expression. Add walked expressions to the head of the SS chain.
8768 A wholly scalar expression will not be added. */
8770 gfc_ss *
8771 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
8773 gfc_ss *head;
8775 switch (expr->expr_type)
8777 case EXPR_VARIABLE:
8778 head = gfc_walk_variable_expr (ss, expr);
8779 return head;
8781 case EXPR_OP:
8782 head = gfc_walk_op_expr (ss, expr);
8783 return head;
8785 case EXPR_FUNCTION:
8786 head = gfc_walk_function_expr (ss, expr);
8787 return head;
8789 case EXPR_CONSTANT:
8790 case EXPR_NULL:
8791 case EXPR_STRUCTURE:
8792 /* Pass back and let the caller deal with it. */
8793 break;
8795 case EXPR_ARRAY:
8796 head = gfc_walk_array_constructor (ss, expr);
8797 return head;
8799 case EXPR_SUBSTRING:
8800 /* Pass back and let the caller deal with it. */
8801 break;
8803 default:
8804 internal_error ("bad expression type during walk (%d)",
8805 expr->expr_type);
8807 return ss;
8811 /* Entry point for expression walking.
8812 A return value equal to the passed chain means this is
8813 a scalar expression. It is up to the caller to take whatever action is
8814 necessary to translate these. */
8816 gfc_ss *
8817 gfc_walk_expr (gfc_expr * expr)
8819 gfc_ss *res;
8821 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
8822 return gfc_reverse_ss (res);