PR c++/14032
[official-gcc.git] / gcc / fortran / trans-array.c
blob69be8efb2f30a2613500012435428ba502bfac9a
1 /* Array translation routines
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* trans-array.c-- Various array related code, including scalarization,
24 allocation, initialization and other support routines. */
26 /* How the scalarizer works.
27 In gfortran, array expressions use the same core routines as scalar
28 expressions.
29 First, a Scalarization State (SS) chain is built. This is done by walking
30 the expression tree, and building a linear list of the terms in the
31 expression. As the tree is walked, scalar subexpressions are translated.
33 The scalarization parameters are stored in a gfc_loopinfo structure.
34 First the start and stride of each term is calculated by
35 gfc_conv_ss_startstride. During this process the expressions for the array
36 descriptors and data pointers are also translated.
38 If the expression is an assignment, we must then resolve any dependencies.
39 In fortran all the rhs values of an assignment must be evaluated before
40 any assignments take place. This can require a temporary array to store the
41 values. We also require a temporary when we are passing array expressions
42 or vector subecripts as procedure parameters.
44 Array sections are passed without copying to a temporary. These use the
45 scalarizer to determine the shape of the section. The flag
46 loop->array_parameter tells the scalarizer that the actual values and loop
47 variables will not be required.
49 The function gfc_conv_loop_setup generates the scalarization setup code.
50 It determines the range of the scalarizing loop variables. If a temporary
51 is required, this is created and initialized. Code for scalar expressions
52 taken outside the loop is also generated at this time. Next the offset and
53 scaling required to translate from loop variables to array indices for each
54 term is calculated.
56 A call to gfc_start_scalarized_body marks the start of the scalarized
57 expression. This creates a scope and declares the loop variables. Before
58 calling this gfc_make_ss_chain_used must be used to indicate which terms
59 will be used inside this loop.
61 The scalar gfc_conv_* functions are then used to build the main body of the
62 scalarization loop. Scalarization loop variables and precalculated scalar
63 values are automatically substituted. Note that gfc_advance_se_ss_chain
64 must be used, rather than changing the se->ss directly.
66 For assignment expressions requiring a temporary two sub loops are
67 generated. The first stores the result of the expression in the temporary,
68 the second copies it to the result. A call to
69 gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
70 the start of the copying loop. The temporary may be less than full rank.
72 Finally gfc_trans_scalarizing_loops is called to generate the implicit do
73 loops. The loops are added to the pre chain of the loopinfo. The post
74 chain may still contain cleanup code.
76 After the loop code has been added into its parent scope gfc_cleanup_loop
77 is called to free all the SS allocated by the scalarizer. */
79 #include "config.h"
80 #include "system.h"
81 #include "coretypes.h"
82 #include "tree.h"
83 #include "tree-gimple.h"
84 #include "ggc.h"
85 #include "toplev.h"
86 #include "real.h"
87 #include "flags.h"
88 #include "gfortran.h"
89 #include "trans.h"
90 #include "trans-stmt.h"
91 #include "trans-types.h"
92 #include "trans-array.h"
93 #include "trans-const.h"
94 #include "dependency.h"
96 static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
97 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor *);
99 /* The contents of this structure aren't actually used, just the address. */
100 static gfc_ss gfc_ss_terminator_var;
101 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
104 static tree
105 gfc_array_dataptr_type (tree desc)
107 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
111 /* Build expressions to access the members of an array descriptor.
112 It's surprisingly easy to mess up here, so never access
113 an array descriptor by "brute force", always use these
114 functions. This also avoids problems if we change the format
115 of an array descriptor.
117 To understand these magic numbers, look at the comments
118 before gfc_build_array_type() in trans-types.c.
120 The code within these defines should be the only code which knows the format
121 of an array descriptor.
123 Any code just needing to read obtain the bounds of an array should use
124 gfc_conv_array_* rather than the following functions as these will return
125 know constant values, and work with arrays which do not have descriptors.
127 Don't forget to #undef these! */
129 #define DATA_FIELD 0
130 #define OFFSET_FIELD 1
131 #define DTYPE_FIELD 2
132 #define DIMENSION_FIELD 3
134 #define STRIDE_SUBFIELD 0
135 #define LBOUND_SUBFIELD 1
136 #define UBOUND_SUBFIELD 2
138 /* This provides READ-ONLY access to the data field. The field itself
139 doesn't have the proper type. */
141 tree
142 gfc_conv_descriptor_data_get (tree desc)
144 tree field, type, t;
146 type = TREE_TYPE (desc);
147 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
149 field = TYPE_FIELDS (type);
150 gcc_assert (DATA_FIELD == 0);
152 t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
153 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
155 return t;
158 /* This provides WRITE access to the data field.
160 TUPLES_P is true if we are generating tuples.
162 This function gets called through the following macros:
163 gfc_conv_descriptor_data_set
164 gfc_conv_descriptor_data_set_tuples. */
166 void
167 gfc_conv_descriptor_data_set_internal (stmtblock_t *block,
168 tree desc, tree value,
169 bool tuples_p)
171 tree field, type, t;
173 type = TREE_TYPE (desc);
174 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
176 field = TYPE_FIELDS (type);
177 gcc_assert (DATA_FIELD == 0);
179 t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
180 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value), tuples_p);
184 /* This provides address access to the data field. This should only be
185 used by array allocation, passing this on to the runtime. */
187 tree
188 gfc_conv_descriptor_data_addr (tree desc)
190 tree field, type, t;
192 type = TREE_TYPE (desc);
193 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
195 field = TYPE_FIELDS (type);
196 gcc_assert (DATA_FIELD == 0);
198 t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
199 return build_fold_addr_expr (t);
202 tree
203 gfc_conv_descriptor_offset (tree desc)
205 tree type;
206 tree field;
208 type = TREE_TYPE (desc);
209 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
211 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
212 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
214 return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
217 tree
218 gfc_conv_descriptor_dtype (tree desc)
220 tree field;
221 tree type;
223 type = TREE_TYPE (desc);
224 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
226 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
227 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
229 return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
232 static tree
233 gfc_conv_descriptor_dimension (tree desc, tree dim)
235 tree field;
236 tree type;
237 tree tmp;
239 type = TREE_TYPE (desc);
240 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
242 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
243 gcc_assert (field != NULL_TREE
244 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
245 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
247 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
248 tmp = gfc_build_array_ref (tmp, dim);
249 return tmp;
252 tree
253 gfc_conv_descriptor_stride (tree desc, tree dim)
255 tree tmp;
256 tree field;
258 tmp = gfc_conv_descriptor_dimension (desc, dim);
259 field = TYPE_FIELDS (TREE_TYPE (tmp));
260 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
261 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
263 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
264 return tmp;
267 tree
268 gfc_conv_descriptor_lbound (tree desc, tree dim)
270 tree tmp;
271 tree field;
273 tmp = gfc_conv_descriptor_dimension (desc, dim);
274 field = TYPE_FIELDS (TREE_TYPE (tmp));
275 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
276 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
278 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
279 return tmp;
282 tree
283 gfc_conv_descriptor_ubound (tree desc, tree dim)
285 tree tmp;
286 tree field;
288 tmp = gfc_conv_descriptor_dimension (desc, dim);
289 field = TYPE_FIELDS (TREE_TYPE (tmp));
290 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
291 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
293 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
294 return tmp;
298 /* Build a null array descriptor constructor. */
300 tree
301 gfc_build_null_descriptor (tree type)
303 tree field;
304 tree tmp;
306 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
307 gcc_assert (DATA_FIELD == 0);
308 field = TYPE_FIELDS (type);
310 /* Set a NULL data pointer. */
311 tmp = build_constructor_single (type, field, null_pointer_node);
312 TREE_CONSTANT (tmp) = 1;
313 TREE_INVARIANT (tmp) = 1;
314 /* All other fields are ignored. */
316 return tmp;
320 /* Cleanup those #defines. */
322 #undef DATA_FIELD
323 #undef OFFSET_FIELD
324 #undef DTYPE_FIELD
325 #undef DIMENSION_FIELD
326 #undef STRIDE_SUBFIELD
327 #undef LBOUND_SUBFIELD
328 #undef UBOUND_SUBFIELD
331 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
332 flags & 1 = Main loop body.
333 flags & 2 = temp copy loop. */
335 void
336 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
338 for (; ss != gfc_ss_terminator; ss = ss->next)
339 ss->useflags = flags;
342 static void gfc_free_ss (gfc_ss *);
345 /* Free a gfc_ss chain. */
347 static void
348 gfc_free_ss_chain (gfc_ss * ss)
350 gfc_ss *next;
352 while (ss != gfc_ss_terminator)
354 gcc_assert (ss != NULL);
355 next = ss->next;
356 gfc_free_ss (ss);
357 ss = next;
362 /* Free a SS. */
364 static void
365 gfc_free_ss (gfc_ss * ss)
367 int n;
369 switch (ss->type)
371 case GFC_SS_SECTION:
372 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
374 if (ss->data.info.subscript[n])
375 gfc_free_ss_chain (ss->data.info.subscript[n]);
377 break;
379 default:
380 break;
383 gfc_free (ss);
387 /* Free all the SS associated with a loop. */
389 void
390 gfc_cleanup_loop (gfc_loopinfo * loop)
392 gfc_ss *ss;
393 gfc_ss *next;
395 ss = loop->ss;
396 while (ss != gfc_ss_terminator)
398 gcc_assert (ss != NULL);
399 next = ss->loop_chain;
400 gfc_free_ss (ss);
401 ss = next;
406 /* Associate a SS chain with a loop. */
408 void
409 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
411 gfc_ss *ss;
413 if (head == gfc_ss_terminator)
414 return;
416 ss = head;
417 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
419 if (ss->next == gfc_ss_terminator)
420 ss->loop_chain = loop->ss;
421 else
422 ss->loop_chain = ss->next;
424 gcc_assert (ss == gfc_ss_terminator);
425 loop->ss = head;
429 /* Generate an initializer for a static pointer or allocatable array. */
431 void
432 gfc_trans_static_array_pointer (gfc_symbol * sym)
434 tree type;
436 gcc_assert (TREE_STATIC (sym->backend_decl));
437 /* Just zero the data member. */
438 type = TREE_TYPE (sym->backend_decl);
439 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
443 /* If the bounds of SE's loop have not yet been set, see if they can be
444 determined from array spec AS, which is the array spec of a called
445 function. MAPPING maps the callee's dummy arguments to the values
446 that the caller is passing. Add any initialization and finalization
447 code to SE. */
449 void
450 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
451 gfc_se * se, gfc_array_spec * as)
453 int n, dim;
454 gfc_se tmpse;
455 tree lower;
456 tree upper;
457 tree tmp;
459 if (as && as->type == AS_EXPLICIT)
460 for (dim = 0; dim < se->loop->dimen; dim++)
462 n = se->loop->order[dim];
463 if (se->loop->to[n] == NULL_TREE)
465 /* Evaluate the lower bound. */
466 gfc_init_se (&tmpse, NULL);
467 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
468 gfc_add_block_to_block (&se->pre, &tmpse.pre);
469 gfc_add_block_to_block (&se->post, &tmpse.post);
470 lower = tmpse.expr;
472 /* ...and the upper bound. */
473 gfc_init_se (&tmpse, NULL);
474 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
475 gfc_add_block_to_block (&se->pre, &tmpse.pre);
476 gfc_add_block_to_block (&se->post, &tmpse.post);
477 upper = tmpse.expr;
479 /* Set the upper bound of the loop to UPPER - LOWER. */
480 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
481 tmp = gfc_evaluate_now (tmp, &se->pre);
482 se->loop->to[n] = tmp;
488 /* Generate code to allocate an array temporary, or create a variable to
489 hold the data. If size is NULL, zero the descriptor so that the
490 callee will allocate the array. If DEALLOC is true, also generate code to
491 free the array afterwards.
493 Initialization code is added to PRE and finalization code to POST.
494 DYNAMIC is true if the caller may want to extend the array later
495 using realloc. This prevents us from putting the array on the stack. */
497 static void
498 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
499 gfc_ss_info * info, tree size, tree nelem,
500 bool dynamic, bool dealloc)
502 tree tmp;
503 tree desc;
504 bool onstack;
506 desc = info->descriptor;
507 info->offset = gfc_index_zero_node;
508 if (size == NULL_TREE || integer_zerop (size))
510 /* A callee allocated array. */
511 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
512 onstack = FALSE;
514 else
516 /* Allocate the temporary. */
517 onstack = !dynamic && gfc_can_put_var_on_stack (size);
519 if (onstack)
521 /* Make a temporary variable to hold the data. */
522 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (nelem), nelem,
523 gfc_index_one_node);
524 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
525 tmp);
526 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
527 tmp);
528 tmp = gfc_create_var (tmp, "A");
529 tmp = build_fold_addr_expr (tmp);
530 gfc_conv_descriptor_data_set (pre, desc, tmp);
532 else
534 /* Allocate memory to hold the data. */
535 tmp = gfc_call_malloc (pre, NULL, size);
536 tmp = gfc_evaluate_now (tmp, pre);
537 gfc_conv_descriptor_data_set (pre, desc, tmp);
540 info->data = gfc_conv_descriptor_data_get (desc);
542 /* The offset is zero because we create temporaries with a zero
543 lower bound. */
544 tmp = gfc_conv_descriptor_offset (desc);
545 gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
547 if (dealloc && !onstack)
549 /* Free the temporary. */
550 tmp = gfc_conv_descriptor_data_get (desc);
551 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
552 gfc_add_expr_to_block (post, tmp);
557 /* Generate code to create and initialize the descriptor for a temporary
558 array. This is used for both temporaries needed by the scalarizer, and
559 functions returning arrays. Adjusts the loop variables to be
560 zero-based, and calculates the loop bounds for callee allocated arrays.
561 Allocate the array unless it's callee allocated (we have a callee
562 allocated array if 'callee_alloc' is true, or if loop->to[n] is
563 NULL_TREE for any n). Also fills in the descriptor, data and offset
564 fields of info if known. Returns the size of the array, or NULL for a
565 callee allocated array.
567 PRE, POST, DYNAMIC and DEALLOC are as for gfc_trans_allocate_array_storage.
570 tree
571 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
572 gfc_loopinfo * loop, gfc_ss_info * info,
573 tree eltype, bool dynamic, bool dealloc,
574 bool callee_alloc)
576 tree type;
577 tree desc;
578 tree tmp;
579 tree size;
580 tree nelem;
581 tree cond;
582 tree or_expr;
583 int n;
584 int dim;
586 gcc_assert (info->dimen > 0);
587 /* Set the lower bound to zero. */
588 for (dim = 0; dim < info->dimen; dim++)
590 n = loop->order[dim];
591 if (n < loop->temp_dim)
592 gcc_assert (integer_zerop (loop->from[n]));
593 else
595 /* Callee allocated arrays may not have a known bound yet. */
596 if (loop->to[n])
597 loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
598 loop->to[n], loop->from[n]);
599 loop->from[n] = gfc_index_zero_node;
602 info->delta[dim] = gfc_index_zero_node;
603 info->start[dim] = gfc_index_zero_node;
604 info->end[dim] = gfc_index_zero_node;
605 info->stride[dim] = gfc_index_one_node;
606 info->dim[dim] = dim;
609 /* Initialize the descriptor. */
610 type =
611 gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1);
612 desc = gfc_create_var (type, "atmp");
613 GFC_DECL_PACKED_ARRAY (desc) = 1;
615 info->descriptor = desc;
616 size = gfc_index_one_node;
618 /* Fill in the array dtype. */
619 tmp = gfc_conv_descriptor_dtype (desc);
620 gfc_add_modify_expr (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
623 Fill in the bounds and stride. This is a packed array, so:
625 size = 1;
626 for (n = 0; n < rank; n++)
628 stride[n] = size
629 delta = ubound[n] + 1 - lbound[n];
630 size = size * delta;
632 size = size * sizeof(element);
635 or_expr = NULL_TREE;
637 for (n = 0; n < info->dimen; n++)
639 if (loop->to[n] == NULL_TREE)
641 /* For a callee allocated array express the loop bounds in terms
642 of the descriptor fields. */
643 tmp = build2 (MINUS_EXPR, gfc_array_index_type,
644 gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
645 gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
646 loop->to[n] = tmp;
647 size = NULL_TREE;
648 continue;
651 /* Store the stride and bound components in the descriptor. */
652 tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
653 gfc_add_modify_expr (pre, tmp, size);
655 tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
656 gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
658 tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
659 gfc_add_modify_expr (pre, tmp, loop->to[n]);
661 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
662 loop->to[n], gfc_index_one_node);
664 /* Check whether the size for this dimension is negative. */
665 cond = fold_build2 (LE_EXPR, boolean_type_node, tmp,
666 gfc_index_zero_node);
667 cond = gfc_evaluate_now (cond, pre);
669 if (n == 0)
670 or_expr = cond;
671 else
672 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
674 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
675 size = gfc_evaluate_now (size, pre);
678 /* Get the size of the array. */
680 if (size && !callee_alloc)
682 /* If or_expr is true, then the extent in at least one
683 dimension is zero and the size is set to zero. */
684 size = fold_build3 (COND_EXPR, gfc_array_index_type,
685 or_expr, gfc_index_zero_node, size);
687 nelem = size;
688 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
689 fold_convert (gfc_array_index_type,
690 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
692 else
694 nelem = size;
695 size = NULL_TREE;
698 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, dynamic,
699 dealloc);
701 if (info->dimen > loop->temp_dim)
702 loop->temp_dim = info->dimen;
704 return size;
708 /* Generate code to transpose array EXPR by creating a new descriptor
709 in which the dimension specifications have been reversed. */
711 void
712 gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
714 tree dest, src, dest_index, src_index;
715 gfc_loopinfo *loop;
716 gfc_ss_info *dest_info, *src_info;
717 gfc_ss *dest_ss, *src_ss;
718 gfc_se src_se;
719 int n;
721 loop = se->loop;
723 src_ss = gfc_walk_expr (expr);
724 dest_ss = se->ss;
726 src_info = &src_ss->data.info;
727 dest_info = &dest_ss->data.info;
728 gcc_assert (dest_info->dimen == 2);
729 gcc_assert (src_info->dimen == 2);
731 /* Get a descriptor for EXPR. */
732 gfc_init_se (&src_se, NULL);
733 gfc_conv_expr_descriptor (&src_se, expr, src_ss);
734 gfc_add_block_to_block (&se->pre, &src_se.pre);
735 gfc_add_block_to_block (&se->post, &src_se.post);
736 src = src_se.expr;
738 /* Allocate a new descriptor for the return value. */
739 dest = gfc_create_var (TREE_TYPE (src), "atmp");
740 dest_info->descriptor = dest;
741 se->expr = dest;
743 /* Copy across the dtype field. */
744 gfc_add_modify_expr (&se->pre,
745 gfc_conv_descriptor_dtype (dest),
746 gfc_conv_descriptor_dtype (src));
748 /* Copy the dimension information, renumbering dimension 1 to 0 and
749 0 to 1. */
750 for (n = 0; n < 2; n++)
752 dest_info->delta[n] = gfc_index_zero_node;
753 dest_info->start[n] = gfc_index_zero_node;
754 dest_info->end[n] = gfc_index_zero_node;
755 dest_info->stride[n] = gfc_index_one_node;
756 dest_info->dim[n] = n;
758 dest_index = gfc_rank_cst[n];
759 src_index = gfc_rank_cst[1 - n];
761 gfc_add_modify_expr (&se->pre,
762 gfc_conv_descriptor_stride (dest, dest_index),
763 gfc_conv_descriptor_stride (src, src_index));
765 gfc_add_modify_expr (&se->pre,
766 gfc_conv_descriptor_lbound (dest, dest_index),
767 gfc_conv_descriptor_lbound (src, src_index));
769 gfc_add_modify_expr (&se->pre,
770 gfc_conv_descriptor_ubound (dest, dest_index),
771 gfc_conv_descriptor_ubound (src, src_index));
773 if (!loop->to[n])
775 gcc_assert (integer_zerop (loop->from[n]));
776 loop->to[n] = build2 (MINUS_EXPR, gfc_array_index_type,
777 gfc_conv_descriptor_ubound (dest, dest_index),
778 gfc_conv_descriptor_lbound (dest, dest_index));
782 /* Copy the data pointer. */
783 dest_info->data = gfc_conv_descriptor_data_get (src);
784 gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);
786 /* Copy the offset. This is not changed by transposition; the top-left
787 element is still at the same offset as before, except where the loop
788 starts at zero. */
789 if (!integer_zerop (loop->from[0]))
790 dest_info->offset = gfc_conv_descriptor_offset (src);
791 else
792 dest_info->offset = gfc_index_zero_node;
794 gfc_add_modify_expr (&se->pre,
795 gfc_conv_descriptor_offset (dest),
796 dest_info->offset);
798 if (dest_info->dimen > loop->temp_dim)
799 loop->temp_dim = dest_info->dimen;
803 /* Return the number of iterations in a loop that starts at START,
804 ends at END, and has step STEP. */
806 static tree
807 gfc_get_iteration_count (tree start, tree end, tree step)
809 tree tmp;
810 tree type;
812 type = TREE_TYPE (step);
813 tmp = fold_build2 (MINUS_EXPR, type, end, start);
814 tmp = fold_build2 (FLOOR_DIV_EXPR, type, tmp, step);
815 tmp = fold_build2 (PLUS_EXPR, type, tmp, build_int_cst (type, 1));
816 tmp = fold_build2 (MAX_EXPR, type, tmp, build_int_cst (type, 0));
817 return fold_convert (gfc_array_index_type, tmp);
821 /* Extend the data in array DESC by EXTRA elements. */
823 static void
824 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
826 tree arg0, arg1;
827 tree tmp;
828 tree size;
829 tree ubound;
831 if (integer_zerop (extra))
832 return;
834 ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
836 /* Add EXTRA to the upper bound. */
837 tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
838 gfc_add_modify_expr (pblock, ubound, tmp);
840 /* Get the value of the current data pointer. */
841 arg0 = gfc_conv_descriptor_data_get (desc);
843 /* Calculate the new array size. */
844 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
845 tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, gfc_index_one_node);
846 arg1 = build2 (MULT_EXPR, size_type_node, fold_convert (size_type_node, tmp),
847 fold_convert (size_type_node, size));
849 /* Call the realloc() function. */
850 tmp = gfc_call_realloc (pblock, arg0, arg1);
851 gfc_conv_descriptor_data_set (pblock, desc, tmp);
855 /* Return true if the bounds of iterator I can only be determined
856 at run time. */
858 static inline bool
859 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
861 return (i->start->expr_type != EXPR_CONSTANT
862 || i->end->expr_type != EXPR_CONSTANT
863 || i->step->expr_type != EXPR_CONSTANT);
867 /* Split the size of constructor element EXPR into the sum of two terms,
868 one of which can be determined at compile time and one of which must
869 be calculated at run time. Set *SIZE to the former and return true
870 if the latter might be nonzero. */
872 static bool
873 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
875 if (expr->expr_type == EXPR_ARRAY)
876 return gfc_get_array_constructor_size (size, expr->value.constructor);
877 else if (expr->rank > 0)
879 /* Calculate everything at run time. */
880 mpz_set_ui (*size, 0);
881 return true;
883 else
885 /* A single element. */
886 mpz_set_ui (*size, 1);
887 return false;
892 /* Like gfc_get_array_constructor_element_size, but applied to the whole
893 of array constructor C. */
895 static bool
896 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
898 gfc_iterator *i;
899 mpz_t val;
900 mpz_t len;
901 bool dynamic;
903 mpz_set_ui (*size, 0);
904 mpz_init (len);
905 mpz_init (val);
907 dynamic = false;
908 for (; c; c = c->next)
910 i = c->iterator;
911 if (i && gfc_iterator_has_dynamic_bounds (i))
912 dynamic = true;
913 else
915 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
916 if (i)
918 /* Multiply the static part of the element size by the
919 number of iterations. */
920 mpz_sub (val, i->end->value.integer, i->start->value.integer);
921 mpz_fdiv_q (val, val, i->step->value.integer);
922 mpz_add_ui (val, val, 1);
923 if (mpz_sgn (val) > 0)
924 mpz_mul (len, len, val);
925 else
926 mpz_set_ui (len, 0);
928 mpz_add (*size, *size, len);
931 mpz_clear (len);
932 mpz_clear (val);
933 return dynamic;
937 /* Make sure offset is a variable. */
939 static void
940 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
941 tree * offsetvar)
943 /* We should have already created the offset variable. We cannot
944 create it here because we may be in an inner scope. */
945 gcc_assert (*offsetvar != NULL_TREE);
946 gfc_add_modify_expr (pblock, *offsetvar, *poffset);
947 *poffset = *offsetvar;
948 TREE_USED (*offsetvar) = 1;
952 /* Assign an element of an array constructor. */
954 static void
955 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
956 tree offset, gfc_se * se, gfc_expr * expr)
958 tree tmp;
960 gfc_conv_expr (se, expr);
962 /* Store the value. */
963 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
964 tmp = gfc_build_array_ref (tmp, offset);
965 if (expr->ts.type == BT_CHARACTER)
967 gfc_conv_string_parameter (se);
968 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
970 /* The temporary is an array of pointers. */
971 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
972 gfc_add_modify_expr (&se->pre, tmp, se->expr);
974 else
976 /* The temporary is an array of string values. */
977 tmp = gfc_build_addr_expr (pchar_type_node, tmp);
978 /* We know the temporary and the value will be the same length,
979 so can use memcpy. */
980 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
981 tmp, se->expr, se->string_length);
982 gfc_add_expr_to_block (&se->pre, tmp);
985 else
987 /* TODO: Should the frontend already have done this conversion? */
988 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
989 gfc_add_modify_expr (&se->pre, tmp, se->expr);
992 gfc_add_block_to_block (pblock, &se->pre);
993 gfc_add_block_to_block (pblock, &se->post);
997 /* Add the contents of an array to the constructor. DYNAMIC is as for
998 gfc_trans_array_constructor_value. */
1000 static void
1001 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1002 tree type ATTRIBUTE_UNUSED,
1003 tree desc, gfc_expr * expr,
1004 tree * poffset, tree * offsetvar,
1005 bool dynamic)
1007 gfc_se se;
1008 gfc_ss *ss;
1009 gfc_loopinfo loop;
1010 stmtblock_t body;
1011 tree tmp;
1012 tree size;
1013 int n;
1015 /* We need this to be a variable so we can increment it. */
1016 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1018 gfc_init_se (&se, NULL);
1020 /* Walk the array expression. */
1021 ss = gfc_walk_expr (expr);
1022 gcc_assert (ss != gfc_ss_terminator);
1024 /* Initialize the scalarizer. */
1025 gfc_init_loopinfo (&loop);
1026 gfc_add_ss_to_loop (&loop, ss);
1028 /* Initialize the loop. */
1029 gfc_conv_ss_startstride (&loop);
1030 gfc_conv_loop_setup (&loop);
1032 /* Make sure the constructed array has room for the new data. */
1033 if (dynamic)
1035 /* Set SIZE to the total number of elements in the subarray. */
1036 size = gfc_index_one_node;
1037 for (n = 0; n < loop.dimen; n++)
1039 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1040 gfc_index_one_node);
1041 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1044 /* Grow the constructed array by SIZE elements. */
1045 gfc_grow_array (&loop.pre, desc, size);
1048 /* Make the loop body. */
1049 gfc_mark_ss_chain_used (ss, 1);
1050 gfc_start_scalarized_body (&loop, &body);
1051 gfc_copy_loopinfo_to_se (&se, &loop);
1052 se.ss = ss;
1054 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1055 gcc_assert (se.ss == gfc_ss_terminator);
1057 /* Increment the offset. */
1058 tmp = build2 (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node);
1059 gfc_add_modify_expr (&body, *poffset, tmp);
1061 /* Finish the loop. */
1062 gfc_trans_scalarizing_loops (&loop, &body);
1063 gfc_add_block_to_block (&loop.pre, &loop.post);
1064 tmp = gfc_finish_block (&loop.pre);
1065 gfc_add_expr_to_block (pblock, tmp);
1067 gfc_cleanup_loop (&loop);
1071 /* Assign the values to the elements of an array constructor. DYNAMIC
1072 is true if descriptor DESC only contains enough data for the static
1073 size calculated by gfc_get_array_constructor_size. When true, memory
1074 for the dynamic parts must be allocated using realloc. */
1076 static void
1077 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1078 tree desc, gfc_constructor * c,
1079 tree * poffset, tree * offsetvar,
1080 bool dynamic)
1082 tree tmp;
1083 stmtblock_t body;
1084 gfc_se se;
1085 mpz_t size;
1087 mpz_init (size);
1088 for (; c; c = c->next)
1090 /* If this is an iterator or an array, the offset must be a variable. */
1091 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1092 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1094 gfc_start_block (&body);
1096 if (c->expr->expr_type == EXPR_ARRAY)
1098 /* Array constructors can be nested. */
1099 gfc_trans_array_constructor_value (&body, type, desc,
1100 c->expr->value.constructor,
1101 poffset, offsetvar, dynamic);
1103 else if (c->expr->rank > 0)
1105 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1106 poffset, offsetvar, dynamic);
1108 else
1110 /* This code really upsets the gimplifier so don't bother for now. */
1111 gfc_constructor *p;
1112 HOST_WIDE_INT n;
1113 HOST_WIDE_INT size;
1115 p = c;
1116 n = 0;
1117 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1119 p = p->next;
1120 n++;
1122 if (n < 4)
1124 /* Scalar values. */
1125 gfc_init_se (&se, NULL);
1126 gfc_trans_array_ctor_element (&body, desc, *poffset,
1127 &se, c->expr);
1129 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1130 *poffset, gfc_index_one_node);
1132 else
1134 /* Collect multiple scalar constants into a constructor. */
1135 tree list;
1136 tree init;
1137 tree bound;
1138 tree tmptype;
1140 p = c;
1141 list = NULL_TREE;
1142 /* Count the number of consecutive scalar constants. */
1143 while (p && !(p->iterator
1144 || p->expr->expr_type != EXPR_CONSTANT))
1146 gfc_init_se (&se, NULL);
1147 gfc_conv_constant (&se, p->expr);
1148 if (p->expr->ts.type == BT_CHARACTER
1149 && POINTER_TYPE_P (type))
1151 /* For constant character array constructors we build
1152 an array of pointers. */
1153 se.expr = gfc_build_addr_expr (pchar_type_node,
1154 se.expr);
1157 list = tree_cons (NULL_TREE, se.expr, list);
1158 c = p;
1159 p = p->next;
1162 bound = build_int_cst (NULL_TREE, n - 1);
1163 /* Create an array type to hold them. */
1164 tmptype = build_range_type (gfc_array_index_type,
1165 gfc_index_zero_node, bound);
1166 tmptype = build_array_type (type, tmptype);
1168 init = build_constructor_from_list (tmptype, nreverse (list));
1169 TREE_CONSTANT (init) = 1;
1170 TREE_INVARIANT (init) = 1;
1171 TREE_STATIC (init) = 1;
1172 /* Create a static variable to hold the data. */
1173 tmp = gfc_create_var (tmptype, "data");
1174 TREE_STATIC (tmp) = 1;
1175 TREE_CONSTANT (tmp) = 1;
1176 TREE_INVARIANT (tmp) = 1;
1177 TREE_READONLY (tmp) = 1;
1178 DECL_INITIAL (tmp) = init;
1179 init = tmp;
1181 /* Use BUILTIN_MEMCPY to assign the values. */
1182 tmp = gfc_conv_descriptor_data_get (desc);
1183 tmp = build_fold_indirect_ref (tmp);
1184 tmp = gfc_build_array_ref (tmp, *poffset);
1185 tmp = build_fold_addr_expr (tmp);
1186 init = build_fold_addr_expr (init);
1188 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1189 bound = build_int_cst (NULL_TREE, n * size);
1190 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
1191 tmp, init, bound);
1192 gfc_add_expr_to_block (&body, tmp);
1194 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1195 *poffset,
1196 build_int_cst (gfc_array_index_type, n));
1198 if (!INTEGER_CST_P (*poffset))
1200 gfc_add_modify_expr (&body, *offsetvar, *poffset);
1201 *poffset = *offsetvar;
1205 /* The frontend should already have done any expansions possible
1206 at compile-time. */
1207 if (!c->iterator)
1209 /* Pass the code as is. */
1210 tmp = gfc_finish_block (&body);
1211 gfc_add_expr_to_block (pblock, tmp);
1213 else
1215 /* Build the implied do-loop. */
1216 tree cond;
1217 tree end;
1218 tree step;
1219 tree loopvar;
1220 tree exit_label;
1221 tree loopbody;
1222 tree tmp2;
1223 tree tmp_loopvar;
1225 loopbody = gfc_finish_block (&body);
1227 gfc_init_se (&se, NULL);
1228 gfc_conv_expr (&se, c->iterator->var);
1229 gfc_add_block_to_block (pblock, &se.pre);
1230 loopvar = se.expr;
1232 /* Make a temporary, store the current value in that
1233 and return it, once the loop is done. */
1234 tmp_loopvar = gfc_create_var (TREE_TYPE (loopvar), "loopvar");
1235 gfc_add_modify_expr (pblock, tmp_loopvar, loopvar);
1237 /* Initialize the loop. */
1238 gfc_init_se (&se, NULL);
1239 gfc_conv_expr_val (&se, c->iterator->start);
1240 gfc_add_block_to_block (pblock, &se.pre);
1241 gfc_add_modify_expr (pblock, loopvar, se.expr);
1243 gfc_init_se (&se, NULL);
1244 gfc_conv_expr_val (&se, c->iterator->end);
1245 gfc_add_block_to_block (pblock, &se.pre);
1246 end = gfc_evaluate_now (se.expr, pblock);
1248 gfc_init_se (&se, NULL);
1249 gfc_conv_expr_val (&se, c->iterator->step);
1250 gfc_add_block_to_block (pblock, &se.pre);
1251 step = gfc_evaluate_now (se.expr, pblock);
1253 /* If this array expands dynamically, and the number of iterations
1254 is not constant, we won't have allocated space for the static
1255 part of C->EXPR's size. Do that now. */
1256 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1258 /* Get the number of iterations. */
1259 tmp = gfc_get_iteration_count (loopvar, end, step);
1261 /* Get the static part of C->EXPR's size. */
1262 gfc_get_array_constructor_element_size (&size, c->expr);
1263 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1265 /* Grow the array by TMP * TMP2 elements. */
1266 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
1267 gfc_grow_array (pblock, desc, tmp);
1270 /* Generate the loop body. */
1271 exit_label = gfc_build_label_decl (NULL_TREE);
1272 gfc_start_block (&body);
1274 /* Generate the exit condition. Depending on the sign of
1275 the step variable we have to generate the correct
1276 comparison. */
1277 tmp = fold_build2 (GT_EXPR, boolean_type_node, step,
1278 build_int_cst (TREE_TYPE (step), 0));
1279 cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
1280 build2 (GT_EXPR, boolean_type_node,
1281 loopvar, end),
1282 build2 (LT_EXPR, boolean_type_node,
1283 loopvar, end));
1284 tmp = build1_v (GOTO_EXPR, exit_label);
1285 TREE_USED (exit_label) = 1;
1286 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1287 gfc_add_expr_to_block (&body, tmp);
1289 /* The main loop body. */
1290 gfc_add_expr_to_block (&body, loopbody);
1292 /* Increase loop variable by step. */
1293 tmp = build2 (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
1294 gfc_add_modify_expr (&body, loopvar, tmp);
1296 /* Finish the loop. */
1297 tmp = gfc_finish_block (&body);
1298 tmp = build1_v (LOOP_EXPR, tmp);
1299 gfc_add_expr_to_block (pblock, tmp);
1301 /* Add the exit label. */
1302 tmp = build1_v (LABEL_EXPR, exit_label);
1303 gfc_add_expr_to_block (pblock, tmp);
1305 /* Restore the original value of the loop counter. */
1306 gfc_add_modify_expr (pblock, loopvar, tmp_loopvar);
1309 mpz_clear (size);
1313 /* Figure out the string length of a variable reference expression.
1314 Used by get_array_ctor_strlen. */
1316 static void
1317 get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1319 gfc_ref *ref;
1320 gfc_typespec *ts;
1321 mpz_t char_len;
1323 /* Don't bother if we already know the length is a constant. */
1324 if (*len && INTEGER_CST_P (*len))
1325 return;
1327 ts = &expr->symtree->n.sym->ts;
1328 for (ref = expr->ref; ref; ref = ref->next)
1330 switch (ref->type)
1332 case REF_ARRAY:
1333 /* Array references don't change the string length. */
1334 break;
1336 case REF_COMPONENT:
1337 /* Use the length of the component. */
1338 ts = &ref->u.c.component->ts;
1339 break;
1341 case REF_SUBSTRING:
1342 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1343 || ref->u.ss.start->expr_type != EXPR_CONSTANT)
1344 break;
1345 mpz_init_set_ui (char_len, 1);
1346 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1347 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1348 *len = gfc_conv_mpz_to_tree (char_len,
1349 gfc_default_character_kind);
1350 *len = convert (gfc_charlen_type_node, *len);
1351 mpz_clear (char_len);
1352 return;
1354 default:
1355 /* TODO: Substrings are tricky because we can't evaluate the
1356 expression more than once. For now we just give up, and hope
1357 we can figure it out elsewhere. */
1358 return;
1362 *len = ts->cl->backend_decl;
1366 /* A catch-all to obtain the string length for anything that is not a
1367 constant, array or variable. */
1368 static void
1369 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1371 gfc_se se;
1372 gfc_ss *ss;
1374 /* Don't bother if we already know the length is a constant. */
1375 if (*len && INTEGER_CST_P (*len))
1376 return;
1378 if (!e->ref && e->ts.cl && e->ts.cl->length
1379 && e->ts.cl->length->expr_type == EXPR_CONSTANT)
1381 /* This is easy. */
1382 gfc_conv_const_charlen (e->ts.cl);
1383 *len = e->ts.cl->backend_decl;
1385 else
1387 /* Otherwise, be brutal even if inefficient. */
1388 ss = gfc_walk_expr (e);
1389 gfc_init_se (&se, NULL);
1391 /* No function call, in case of side effects. */
1392 se.no_function_call = 1;
1393 if (ss == gfc_ss_terminator)
1394 gfc_conv_expr (&se, e);
1395 else
1396 gfc_conv_expr_descriptor (&se, e, ss);
1398 /* Fix the value. */
1399 *len = gfc_evaluate_now (se.string_length, &se.pre);
1401 gfc_add_block_to_block (block, &se.pre);
1402 gfc_add_block_to_block (block, &se.post);
1404 e->ts.cl->backend_decl = *len;
1409 /* Figure out the string length of a character array constructor.
1410 Returns TRUE if all elements are character constants. */
1412 bool
1413 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
1415 bool is_const;
1417 is_const = TRUE;
1419 if (c == NULL)
1421 *len = build_int_cstu (gfc_charlen_type_node, 0);
1422 return is_const;
1425 for (; c; c = c->next)
1427 switch (c->expr->expr_type)
1429 case EXPR_CONSTANT:
1430 if (!(*len && INTEGER_CST_P (*len)))
1431 *len = build_int_cstu (gfc_charlen_type_node,
1432 c->expr->value.character.length);
1433 break;
1435 case EXPR_ARRAY:
1436 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1437 is_const = false;
1438 break;
1440 case EXPR_VARIABLE:
1441 is_const = false;
1442 get_array_ctor_var_strlen (c->expr, len);
1443 break;
1445 default:
1446 is_const = false;
1447 get_array_ctor_all_strlen (block, c->expr, len);
1448 break;
1452 return is_const;
1455 /* Check whether the array constructor C consists entirely of constant
1456 elements, and if so returns the number of those elements, otherwise
1457 return zero. Note, an empty or NULL array constructor returns zero. */
1459 unsigned HOST_WIDE_INT
1460 gfc_constant_array_constructor_p (gfc_constructor * c)
1462 unsigned HOST_WIDE_INT nelem = 0;
1464 while (c)
1466 if (c->iterator
1467 || c->expr->rank > 0
1468 || c->expr->expr_type != EXPR_CONSTANT)
1469 return 0;
1470 c = c->next;
1471 nelem++;
1473 return nelem;
1477 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1478 and the tree type of it's elements, TYPE, return a static constant
1479 variable that is compile-time initialized. */
1481 tree
1482 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1484 tree tmptype, list, init, tmp;
1485 HOST_WIDE_INT nelem;
1486 gfc_constructor *c;
1487 gfc_array_spec as;
1488 gfc_se se;
1489 int i;
1491 /* First traverse the constructor list, converting the constants
1492 to tree to build an initializer. */
1493 nelem = 0;
1494 list = NULL_TREE;
1495 c = expr->value.constructor;
1496 while (c)
1498 gfc_init_se (&se, NULL);
1499 gfc_conv_constant (&se, c->expr);
1500 if (c->expr->ts.type == BT_CHARACTER
1501 && POINTER_TYPE_P (type))
1502 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
1503 list = tree_cons (NULL_TREE, se.expr, list);
1504 c = c->next;
1505 nelem++;
1508 /* Next determine the tree type for the array. We use the gfortran
1509 front-end's gfc_get_nodesc_array_type in order to create a suitable
1510 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1512 memset (&as, 0, sizeof (gfc_array_spec));
1514 as.rank = expr->rank;
1515 as.type = AS_EXPLICIT;
1516 if (!expr->shape)
1518 as.lower[0] = gfc_int_expr (0);
1519 as.upper[0] = gfc_int_expr (nelem - 1);
1521 else
1522 for (i = 0; i < expr->rank; i++)
1524 int tmp = (int) mpz_get_si (expr->shape[i]);
1525 as.lower[i] = gfc_int_expr (0);
1526 as.upper[i] = gfc_int_expr (tmp - 1);
1529 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
1531 init = build_constructor_from_list (tmptype, nreverse (list));
1533 TREE_CONSTANT (init) = 1;
1534 TREE_INVARIANT (init) = 1;
1535 TREE_STATIC (init) = 1;
1537 tmp = gfc_create_var (tmptype, "A");
1538 TREE_STATIC (tmp) = 1;
1539 TREE_CONSTANT (tmp) = 1;
1540 TREE_INVARIANT (tmp) = 1;
1541 TREE_READONLY (tmp) = 1;
1542 DECL_INITIAL (tmp) = init;
1544 return tmp;
1548 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1549 This mostly initializes the scalarizer state info structure with the
1550 appropriate values to directly use the array created by the function
1551 gfc_build_constant_array_constructor. */
1553 static void
1554 gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
1555 gfc_ss * ss, tree type)
1557 gfc_ss_info *info;
1558 tree tmp;
1559 int i;
1561 tmp = gfc_build_constant_array_constructor (ss->expr, type);
1563 info = &ss->data.info;
1565 info->descriptor = tmp;
1566 info->data = build_fold_addr_expr (tmp);
1567 info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type,
1568 loop->from[0]);
1570 for (i = 0; i < info->dimen; i++)
1572 info->delta[i] = gfc_index_zero_node;
1573 info->start[i] = gfc_index_zero_node;
1574 info->end[i] = gfc_index_zero_node;
1575 info->stride[i] = gfc_index_one_node;
1576 info->dim[i] = i;
1579 if (info->dimen > loop->temp_dim)
1580 loop->temp_dim = info->dimen;
1583 /* Helper routine of gfc_trans_array_constructor to determine if the
1584 bounds of the loop specified by LOOP are constant and simple enough
1585 to use with gfc_trans_constant_array_constructor. Returns the
1586 the iteration count of the loop if suitable, and NULL_TREE otherwise. */
1588 static tree
1589 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1591 tree size = gfc_index_one_node;
1592 tree tmp;
1593 int i;
1595 for (i = 0; i < loop->dimen; i++)
1597 /* If the bounds aren't constant, return NULL_TREE. */
1598 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1599 return NULL_TREE;
1600 if (!integer_zerop (loop->from[i]))
1602 /* Only allow nonzero "from" in one-dimensional arrays. */
1603 if (loop->dimen != 1)
1604 return NULL_TREE;
1605 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1606 loop->to[i], loop->from[i]);
1608 else
1609 tmp = loop->to[i];
1610 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1611 tmp, gfc_index_one_node);
1612 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1615 return size;
1619 /* Array constructors are handled by constructing a temporary, then using that
1620 within the scalarization loop. This is not optimal, but seems by far the
1621 simplest method. */
1623 static void
1624 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
1626 gfc_constructor *c;
1627 tree offset;
1628 tree offsetvar;
1629 tree desc;
1630 tree type;
1631 bool dynamic;
1633 ss->data.info.dimen = loop->dimen;
1635 c = ss->expr->value.constructor;
1636 if (ss->expr->ts.type == BT_CHARACTER)
1638 bool const_string = get_array_ctor_strlen (&loop->pre, c, &ss->string_length);
1639 if (!ss->string_length)
1640 gfc_todo_error ("complex character array constructors");
1642 ss->expr->ts.cl->backend_decl = ss->string_length;
1644 type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1645 if (const_string)
1646 type = build_pointer_type (type);
1648 else
1649 type = gfc_typenode_for_spec (&ss->expr->ts);
1651 /* See if the constructor determines the loop bounds. */
1652 dynamic = false;
1654 if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
1656 /* We have a multidimensional parameter. */
1657 int n;
1658 for (n = 0; n < ss->expr->rank; n++)
1660 loop->from[n] = gfc_index_zero_node;
1661 loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
1662 gfc_index_integer_kind);
1663 loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1664 loop->to[n], gfc_index_one_node);
1668 if (loop->to[0] == NULL_TREE)
1670 mpz_t size;
1672 /* We should have a 1-dimensional, zero-based loop. */
1673 gcc_assert (loop->dimen == 1);
1674 gcc_assert (integer_zerop (loop->from[0]));
1676 /* Split the constructor size into a static part and a dynamic part.
1677 Allocate the static size up-front and record whether the dynamic
1678 size might be nonzero. */
1679 mpz_init (size);
1680 dynamic = gfc_get_array_constructor_size (&size, c);
1681 mpz_sub_ui (size, size, 1);
1682 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1683 mpz_clear (size);
1686 /* Special case constant array constructors. */
1687 if (!dynamic)
1689 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
1690 if (nelem > 0)
1692 tree size = constant_array_constructor_loop_size (loop);
1693 if (size && compare_tree_int (size, nelem) == 0)
1695 gfc_trans_constant_array_constructor (loop, ss, type);
1696 return;
1701 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
1702 type, dynamic, true, false);
1704 desc = ss->data.info.descriptor;
1705 offset = gfc_index_zero_node;
1706 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1707 TREE_NO_WARNING (offsetvar) = 1;
1708 TREE_USED (offsetvar) = 0;
1709 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
1710 &offset, &offsetvar, dynamic);
1712 /* If the array grows dynamically, the upper bound of the loop variable
1713 is determined by the array's final upper bound. */
1714 if (dynamic)
1715 loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
1717 if (TREE_USED (offsetvar))
1718 pushdecl (offsetvar);
1719 else
1720 gcc_assert (INTEGER_CST_P (offset));
1721 #if 0
1722 /* Disable bound checking for now because it's probably broken. */
1723 if (flag_bounds_check)
1725 gcc_unreachable ();
1727 #endif
1731 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
1732 called after evaluating all of INFO's vector dimensions. Go through
1733 each such vector dimension and see if we can now fill in any missing
1734 loop bounds. */
1736 static void
1737 gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
1739 gfc_se se;
1740 tree tmp;
1741 tree desc;
1742 tree zero;
1743 int n;
1744 int dim;
1746 for (n = 0; n < loop->dimen; n++)
1748 dim = info->dim[n];
1749 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
1750 && loop->to[n] == NULL)
1752 /* Loop variable N indexes vector dimension DIM, and we don't
1753 yet know the upper bound of loop variable N. Set it to the
1754 difference between the vector's upper and lower bounds. */
1755 gcc_assert (loop->from[n] == gfc_index_zero_node);
1756 gcc_assert (info->subscript[dim]
1757 && info->subscript[dim]->type == GFC_SS_VECTOR);
1759 gfc_init_se (&se, NULL);
1760 desc = info->subscript[dim]->data.info.descriptor;
1761 zero = gfc_rank_cst[0];
1762 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1763 gfc_conv_descriptor_ubound (desc, zero),
1764 gfc_conv_descriptor_lbound (desc, zero));
1765 tmp = gfc_evaluate_now (tmp, &loop->pre);
1766 loop->to[n] = tmp;
1772 /* Add the pre and post chains for all the scalar expressions in a SS chain
1773 to loop. This is called after the loop parameters have been calculated,
1774 but before the actual scalarizing loops. */
1776 static void
1777 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript)
1779 gfc_se se;
1780 int n;
1782 /* TODO: This can generate bad code if there are ordering dependencies.
1783 eg. a callee allocated function and an unknown size constructor. */
1784 gcc_assert (ss != NULL);
1786 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
1788 gcc_assert (ss);
1790 switch (ss->type)
1792 case GFC_SS_SCALAR:
1793 /* Scalar expression. Evaluate this now. This includes elemental
1794 dimension indices, but not array section bounds. */
1795 gfc_init_se (&se, NULL);
1796 gfc_conv_expr (&se, ss->expr);
1797 gfc_add_block_to_block (&loop->pre, &se.pre);
1799 if (ss->expr->ts.type != BT_CHARACTER)
1801 /* Move the evaluation of scalar expressions outside the
1802 scalarization loop. */
1803 if (subscript)
1804 se.expr = convert(gfc_array_index_type, se.expr);
1805 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
1806 gfc_add_block_to_block (&loop->pre, &se.post);
1808 else
1809 gfc_add_block_to_block (&loop->post, &se.post);
1811 ss->data.scalar.expr = se.expr;
1812 ss->string_length = se.string_length;
1813 break;
1815 case GFC_SS_REFERENCE:
1816 /* Scalar reference. Evaluate this now. */
1817 gfc_init_se (&se, NULL);
1818 gfc_conv_expr_reference (&se, ss->expr);
1819 gfc_add_block_to_block (&loop->pre, &se.pre);
1820 gfc_add_block_to_block (&loop->post, &se.post);
1822 ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
1823 ss->string_length = se.string_length;
1824 break;
1826 case GFC_SS_SECTION:
1827 /* Add the expressions for scalar and vector subscripts. */
1828 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1829 if (ss->data.info.subscript[n])
1830 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true);
1832 gfc_set_vector_loop_bounds (loop, &ss->data.info);
1833 break;
1835 case GFC_SS_VECTOR:
1836 /* Get the vector's descriptor and store it in SS. */
1837 gfc_init_se (&se, NULL);
1838 gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
1839 gfc_add_block_to_block (&loop->pre, &se.pre);
1840 gfc_add_block_to_block (&loop->post, &se.post);
1841 ss->data.info.descriptor = se.expr;
1842 break;
1844 case GFC_SS_INTRINSIC:
1845 gfc_add_intrinsic_ss_code (loop, ss);
1846 break;
1848 case GFC_SS_FUNCTION:
1849 /* Array function return value. We call the function and save its
1850 result in a temporary for use inside the loop. */
1851 gfc_init_se (&se, NULL);
1852 se.loop = loop;
1853 se.ss = ss;
1854 gfc_conv_expr (&se, ss->expr);
1855 gfc_add_block_to_block (&loop->pre, &se.pre);
1856 gfc_add_block_to_block (&loop->post, &se.post);
1857 ss->string_length = se.string_length;
1858 break;
1860 case GFC_SS_CONSTRUCTOR:
1861 gfc_trans_array_constructor (loop, ss);
1862 break;
1864 case GFC_SS_TEMP:
1865 case GFC_SS_COMPONENT:
1866 /* Do nothing. These are handled elsewhere. */
1867 break;
1869 default:
1870 gcc_unreachable ();
1876 /* Translate expressions for the descriptor and data pointer of a SS. */
1877 /*GCC ARRAYS*/
1879 static void
1880 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
1882 gfc_se se;
1883 tree tmp;
1885 /* Get the descriptor for the array to be scalarized. */
1886 gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
1887 gfc_init_se (&se, NULL);
1888 se.descriptor_only = 1;
1889 gfc_conv_expr_lhs (&se, ss->expr);
1890 gfc_add_block_to_block (block, &se.pre);
1891 ss->data.info.descriptor = se.expr;
1892 ss->string_length = se.string_length;
1894 if (base)
1896 /* Also the data pointer. */
1897 tmp = gfc_conv_array_data (se.expr);
1898 /* If this is a variable or address of a variable we use it directly.
1899 Otherwise we must evaluate it now to avoid breaking dependency
1900 analysis by pulling the expressions for elemental array indices
1901 inside the loop. */
1902 if (!(DECL_P (tmp)
1903 || (TREE_CODE (tmp) == ADDR_EXPR
1904 && DECL_P (TREE_OPERAND (tmp, 0)))))
1905 tmp = gfc_evaluate_now (tmp, block);
1906 ss->data.info.data = tmp;
1908 tmp = gfc_conv_array_offset (se.expr);
1909 ss->data.info.offset = gfc_evaluate_now (tmp, block);
1914 /* Initialize a gfc_loopinfo structure. */
1916 void
1917 gfc_init_loopinfo (gfc_loopinfo * loop)
1919 int n;
1921 memset (loop, 0, sizeof (gfc_loopinfo));
1922 gfc_init_block (&loop->pre);
1923 gfc_init_block (&loop->post);
1925 /* Initially scalarize in order. */
1926 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1927 loop->order[n] = n;
1929 loop->ss = gfc_ss_terminator;
1933 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
1934 chain. */
1936 void
1937 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
1939 se->loop = loop;
1943 /* Return an expression for the data pointer of an array. */
1945 tree
1946 gfc_conv_array_data (tree descriptor)
1948 tree type;
1950 type = TREE_TYPE (descriptor);
1951 if (GFC_ARRAY_TYPE_P (type))
1953 if (TREE_CODE (type) == POINTER_TYPE)
1954 return descriptor;
1955 else
1957 /* Descriptorless arrays. */
1958 return build_fold_addr_expr (descriptor);
1961 else
1962 return gfc_conv_descriptor_data_get (descriptor);
1966 /* Return an expression for the base offset of an array. */
1968 tree
1969 gfc_conv_array_offset (tree descriptor)
1971 tree type;
1973 type = TREE_TYPE (descriptor);
1974 if (GFC_ARRAY_TYPE_P (type))
1975 return GFC_TYPE_ARRAY_OFFSET (type);
1976 else
1977 return gfc_conv_descriptor_offset (descriptor);
1981 /* Get an expression for the array stride. */
1983 tree
1984 gfc_conv_array_stride (tree descriptor, int dim)
1986 tree tmp;
1987 tree type;
1989 type = TREE_TYPE (descriptor);
1991 /* For descriptorless arrays use the array size. */
1992 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
1993 if (tmp != NULL_TREE)
1994 return tmp;
1996 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
1997 return tmp;
2001 /* Like gfc_conv_array_stride, but for the lower bound. */
2003 tree
2004 gfc_conv_array_lbound (tree descriptor, int dim)
2006 tree tmp;
2007 tree type;
2009 type = TREE_TYPE (descriptor);
2011 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2012 if (tmp != NULL_TREE)
2013 return tmp;
2015 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
2016 return tmp;
2020 /* Like gfc_conv_array_stride, but for the upper bound. */
2022 tree
2023 gfc_conv_array_ubound (tree descriptor, int dim)
2025 tree tmp;
2026 tree type;
2028 type = TREE_TYPE (descriptor);
2030 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2031 if (tmp != NULL_TREE)
2032 return tmp;
2034 /* This should only ever happen when passing an assumed shape array
2035 as an actual parameter. The value will never be used. */
2036 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2037 return gfc_index_zero_node;
2039 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
2040 return tmp;
2044 /* Generate code to perform an array index bound check. */
2046 static tree
2047 gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
2048 locus * where, bool check_upper)
2050 tree fault;
2051 tree tmp;
2052 char *msg;
2053 const char * name = NULL;
2055 if (!flag_bounds_check)
2056 return index;
2058 index = gfc_evaluate_now (index, &se->pre);
2060 /* We find a name for the error message. */
2061 if (se->ss)
2062 name = se->ss->expr->symtree->name;
2064 if (!name && se->loop && se->loop->ss && se->loop->ss->expr
2065 && se->loop->ss->expr->symtree)
2066 name = se->loop->ss->expr->symtree->name;
2068 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2069 && se->loop->ss->loop_chain->expr
2070 && se->loop->ss->loop_chain->expr->symtree)
2071 name = se->loop->ss->loop_chain->expr->symtree->name;
2073 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2074 && se->loop->ss->loop_chain->expr->symtree)
2075 name = se->loop->ss->loop_chain->expr->symtree->name;
2077 if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
2079 if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
2080 && se->loop->ss->expr->value.function.name)
2081 name = se->loop->ss->expr->value.function.name;
2082 else
2083 if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
2084 || se->loop->ss->type == GFC_SS_SCALAR)
2085 name = "unnamed constant";
2088 /* Check lower bound. */
2089 tmp = gfc_conv_array_lbound (descriptor, n);
2090 fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
2091 if (name)
2092 asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded",
2093 gfc_msg_fault, name, n+1);
2094 else
2095 asprintf (&msg, "%s, lower bound of dimension %d exceeded, %%ld is "
2096 "smaller than %%ld", gfc_msg_fault, n+1);
2097 gfc_trans_runtime_check (fault, &se->pre, where, msg,
2098 fold_convert (long_integer_type_node, index),
2099 fold_convert (long_integer_type_node, tmp));
2100 gfc_free (msg);
2102 /* Check upper bound. */
2103 if (check_upper)
2105 tmp = gfc_conv_array_ubound (descriptor, n);
2106 fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
2107 if (name)
2108 asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
2109 " exceeded", gfc_msg_fault, name, n+1);
2110 else
2111 asprintf (&msg, "%s, upper bound of dimension %d exceeded, %%ld is "
2112 "larger than %%ld", gfc_msg_fault, n+1);
2113 gfc_trans_runtime_check (fault, &se->pre, where, msg,
2114 fold_convert (long_integer_type_node, index),
2115 fold_convert (long_integer_type_node, tmp));
2116 gfc_free (msg);
2119 return index;
2123 /* Return the offset for an index. Performs bound checking for elemental
2124 dimensions. Single element references are processed separately. */
2126 static tree
2127 gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
2128 gfc_array_ref * ar, tree stride)
2130 tree index;
2131 tree desc;
2132 tree data;
2134 /* Get the index into the array for this dimension. */
2135 if (ar)
2137 gcc_assert (ar->type != AR_ELEMENT);
2138 switch (ar->dimen_type[dim])
2140 case DIMEN_ELEMENT:
2141 gcc_assert (i == -1);
2142 /* Elemental dimension. */
2143 gcc_assert (info->subscript[dim]
2144 && info->subscript[dim]->type == GFC_SS_SCALAR);
2145 /* We've already translated this value outside the loop. */
2146 index = info->subscript[dim]->data.scalar.expr;
2148 index = gfc_trans_array_bound_check (se, info->descriptor,
2149 index, dim, &ar->where,
2150 (ar->as->type != AS_ASSUMED_SIZE
2151 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2152 break;
2154 case DIMEN_VECTOR:
2155 gcc_assert (info && se->loop);
2156 gcc_assert (info->subscript[dim]
2157 && info->subscript[dim]->type == GFC_SS_VECTOR);
2158 desc = info->subscript[dim]->data.info.descriptor;
2160 /* Get a zero-based index into the vector. */
2161 index = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2162 se->loop->loopvar[i], se->loop->from[i]);
2164 /* Multiply the index by the stride. */
2165 index = fold_build2 (MULT_EXPR, gfc_array_index_type,
2166 index, gfc_conv_array_stride (desc, 0));
2168 /* Read the vector to get an index into info->descriptor. */
2169 data = build_fold_indirect_ref (gfc_conv_array_data (desc));
2170 index = gfc_build_array_ref (data, index);
2171 index = gfc_evaluate_now (index, &se->pre);
2173 /* Do any bounds checking on the final info->descriptor index. */
2174 index = gfc_trans_array_bound_check (se, info->descriptor,
2175 index, dim, &ar->where,
2176 (ar->as->type != AS_ASSUMED_SIZE
2177 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2178 break;
2180 case DIMEN_RANGE:
2181 /* Scalarized dimension. */
2182 gcc_assert (info && se->loop);
2184 /* Multiply the loop variable by the stride and delta. */
2185 index = se->loop->loopvar[i];
2186 if (!integer_onep (info->stride[i]))
2187 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index,
2188 info->stride[i]);
2189 if (!integer_zerop (info->delta[i]))
2190 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index,
2191 info->delta[i]);
2192 break;
2194 default:
2195 gcc_unreachable ();
2198 else
2200 /* Temporary array or derived type component. */
2201 gcc_assert (se->loop);
2202 index = se->loop->loopvar[se->loop->order[i]];
2203 if (!integer_zerop (info->delta[i]))
2204 index = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2205 index, info->delta[i]);
2208 /* Multiply by the stride. */
2209 if (!integer_onep (stride))
2210 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index, stride);
2212 return index;
2216 /* Build a scalarized reference to an array. */
2218 static void
2219 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2221 gfc_ss_info *info;
2222 tree index;
2223 tree tmp;
2224 int n;
2226 info = &se->ss->data.info;
2227 if (ar)
2228 n = se->loop->order[0];
2229 else
2230 n = 0;
2232 index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
2233 info->stride0);
2234 /* Add the offset for this dimension to the stored offset for all other
2235 dimensions. */
2236 if (!integer_zerop (info->offset))
2237 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset);
2239 tmp = build_fold_indirect_ref (info->data);
2240 se->expr = gfc_build_array_ref (tmp, index);
2244 /* Translate access of temporary array. */
2246 void
2247 gfc_conv_tmp_array_ref (gfc_se * se)
2249 se->string_length = se->ss->string_length;
2250 gfc_conv_scalarized_array_ref (se, NULL);
2254 /* Build an array reference. se->expr already holds the array descriptor.
2255 This should be either a variable, indirect variable reference or component
2256 reference. For arrays which do not have a descriptor, se->expr will be
2257 the data pointer.
2258 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2260 void
2261 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2262 locus * where)
2264 int n;
2265 tree index;
2266 tree tmp;
2267 tree stride;
2268 gfc_se indexse;
2270 /* Handle scalarized references separately. */
2271 if (ar->type != AR_ELEMENT)
2273 gfc_conv_scalarized_array_ref (se, ar);
2274 gfc_advance_se_ss_chain (se);
2275 return;
2278 index = gfc_index_zero_node;
2280 /* Calculate the offsets from all the dimensions. */
2281 for (n = 0; n < ar->dimen; n++)
2283 /* Calculate the index for this dimension. */
2284 gfc_init_se (&indexse, se);
2285 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2286 gfc_add_block_to_block (&se->pre, &indexse.pre);
2288 if (flag_bounds_check)
2290 /* Check array bounds. */
2291 tree cond;
2292 char *msg;
2294 /* Evaluate the indexse.expr only once. */
2295 indexse.expr = save_expr (indexse.expr);
2297 /* Lower bound. */
2298 tmp = gfc_conv_array_lbound (se->expr, n);
2299 cond = fold_build2 (LT_EXPR, boolean_type_node,
2300 indexse.expr, tmp);
2301 asprintf (&msg, "%s for array '%s', "
2302 "lower bound of dimension %d exceeded, %%ld is smaller "
2303 "than %%ld", gfc_msg_fault, sym->name, n+1);
2304 gfc_trans_runtime_check (cond, &se->pre, where, msg,
2305 fold_convert (long_integer_type_node,
2306 indexse.expr),
2307 fold_convert (long_integer_type_node, tmp));
2308 gfc_free (msg);
2310 /* Upper bound, but not for the last dimension of assumed-size
2311 arrays. */
2312 if (n < ar->dimen - 1
2313 || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
2315 tmp = gfc_conv_array_ubound (se->expr, n);
2316 cond = fold_build2 (GT_EXPR, boolean_type_node,
2317 indexse.expr, tmp);
2318 asprintf (&msg, "%s for array '%s', "
2319 "upper bound of dimension %d exceeded, %%ld is "
2320 "greater than %%ld", gfc_msg_fault, sym->name, n+1);
2321 gfc_trans_runtime_check (cond, &se->pre, where, msg,
2322 fold_convert (long_integer_type_node,
2323 indexse.expr),
2324 fold_convert (long_integer_type_node, tmp));
2325 gfc_free (msg);
2329 /* Multiply the index by the stride. */
2330 stride = gfc_conv_array_stride (se->expr, n);
2331 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
2332 stride);
2334 /* And add it to the total. */
2335 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2338 tmp = gfc_conv_array_offset (se->expr);
2339 if (!integer_zerop (tmp))
2340 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2342 /* Access the calculated element. */
2343 tmp = gfc_conv_array_data (se->expr);
2344 tmp = build_fold_indirect_ref (tmp);
2345 se->expr = gfc_build_array_ref (tmp, index);
2349 /* Generate the code to be executed immediately before entering a
2350 scalarization loop. */
2352 static void
2353 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2354 stmtblock_t * pblock)
2356 tree index;
2357 tree stride;
2358 gfc_ss_info *info;
2359 gfc_ss *ss;
2360 gfc_se se;
2361 int i;
2363 /* This code will be executed before entering the scalarization loop
2364 for this dimension. */
2365 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2367 if ((ss->useflags & flag) == 0)
2368 continue;
2370 if (ss->type != GFC_SS_SECTION
2371 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2372 && ss->type != GFC_SS_COMPONENT)
2373 continue;
2375 info = &ss->data.info;
2377 if (dim >= info->dimen)
2378 continue;
2380 if (dim == info->dimen - 1)
2382 /* For the outermost loop calculate the offset due to any
2383 elemental dimensions. It will have been initialized with the
2384 base offset of the array. */
2385 if (info->ref)
2387 for (i = 0; i < info->ref->u.ar.dimen; i++)
2389 if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2390 continue;
2392 gfc_init_se (&se, NULL);
2393 se.loop = loop;
2394 se.expr = info->descriptor;
2395 stride = gfc_conv_array_stride (info->descriptor, i);
2396 index = gfc_conv_array_index_offset (&se, info, i, -1,
2397 &info->ref->u.ar,
2398 stride);
2399 gfc_add_block_to_block (pblock, &se.pre);
2401 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2402 info->offset, index);
2403 info->offset = gfc_evaluate_now (info->offset, pblock);
2406 i = loop->order[0];
2407 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2409 else
2410 stride = gfc_conv_array_stride (info->descriptor, 0);
2412 /* Calculate the stride of the innermost loop. Hopefully this will
2413 allow the backend optimizers to do their stuff more effectively.
2415 info->stride0 = gfc_evaluate_now (stride, pblock);
2417 else
2419 /* Add the offset for the previous loop dimension. */
2420 gfc_array_ref *ar;
2422 if (info->ref)
2424 ar = &info->ref->u.ar;
2425 i = loop->order[dim + 1];
2427 else
2429 ar = NULL;
2430 i = dim + 1;
2433 gfc_init_se (&se, NULL);
2434 se.loop = loop;
2435 se.expr = info->descriptor;
2436 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2437 index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
2438 ar, stride);
2439 gfc_add_block_to_block (pblock, &se.pre);
2440 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2441 info->offset, index);
2442 info->offset = gfc_evaluate_now (info->offset, pblock);
2445 /* Remember this offset for the second loop. */
2446 if (dim == loop->temp_dim - 1)
2447 info->saved_offset = info->offset;
2452 /* Start a scalarized expression. Creates a scope and declares loop
2453 variables. */
2455 void
2456 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2458 int dim;
2459 int n;
2460 int flags;
2462 gcc_assert (!loop->array_parameter);
2464 for (dim = loop->dimen - 1; dim >= 0; dim--)
2466 n = loop->order[dim];
2468 gfc_start_block (&loop->code[n]);
2470 /* Create the loop variable. */
2471 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2473 if (dim < loop->temp_dim)
2474 flags = 3;
2475 else
2476 flags = 1;
2477 /* Calculate values that will be constant within this loop. */
2478 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
2480 gfc_start_block (pbody);
2484 /* Generates the actual loop code for a scalarization loop. */
2486 static void
2487 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
2488 stmtblock_t * pbody)
2490 stmtblock_t block;
2491 tree cond;
2492 tree tmp;
2493 tree loopbody;
2494 tree exit_label;
2496 loopbody = gfc_finish_block (pbody);
2498 /* Initialize the loopvar. */
2499 gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]);
2501 exit_label = gfc_build_label_decl (NULL_TREE);
2503 /* Generate the loop body. */
2504 gfc_init_block (&block);
2506 /* The exit condition. */
2507 cond = build2 (GT_EXPR, boolean_type_node, loop->loopvar[n], loop->to[n]);
2508 tmp = build1_v (GOTO_EXPR, exit_label);
2509 TREE_USED (exit_label) = 1;
2510 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
2511 gfc_add_expr_to_block (&block, tmp);
2513 /* The main body. */
2514 gfc_add_expr_to_block (&block, loopbody);
2516 /* Increment the loopvar. */
2517 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
2518 loop->loopvar[n], gfc_index_one_node);
2519 gfc_add_modify_expr (&block, loop->loopvar[n], tmp);
2521 /* Build the loop. */
2522 tmp = gfc_finish_block (&block);
2523 tmp = build1_v (LOOP_EXPR, tmp);
2524 gfc_add_expr_to_block (&loop->code[n], tmp);
2526 /* Add the exit label. */
2527 tmp = build1_v (LABEL_EXPR, exit_label);
2528 gfc_add_expr_to_block (&loop->code[n], tmp);
2532 /* Finishes and generates the loops for a scalarized expression. */
2534 void
2535 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
2537 int dim;
2538 int n;
2539 gfc_ss *ss;
2540 stmtblock_t *pblock;
2541 tree tmp;
2543 pblock = body;
2544 /* Generate the loops. */
2545 for (dim = 0; dim < loop->dimen; dim++)
2547 n = loop->order[dim];
2548 gfc_trans_scalarized_loop_end (loop, n, pblock);
2549 loop->loopvar[n] = NULL_TREE;
2550 pblock = &loop->code[n];
2553 tmp = gfc_finish_block (pblock);
2554 gfc_add_expr_to_block (&loop->pre, tmp);
2556 /* Clear all the used flags. */
2557 for (ss = loop->ss; ss; ss = ss->loop_chain)
2558 ss->useflags = 0;
2562 /* Finish the main body of a scalarized expression, and start the secondary
2563 copying body. */
2565 void
2566 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
2568 int dim;
2569 int n;
2570 stmtblock_t *pblock;
2571 gfc_ss *ss;
2573 pblock = body;
2574 /* We finish as many loops as are used by the temporary. */
2575 for (dim = 0; dim < loop->temp_dim - 1; dim++)
2577 n = loop->order[dim];
2578 gfc_trans_scalarized_loop_end (loop, n, pblock);
2579 loop->loopvar[n] = NULL_TREE;
2580 pblock = &loop->code[n];
2583 /* We don't want to finish the outermost loop entirely. */
2584 n = loop->order[loop->temp_dim - 1];
2585 gfc_trans_scalarized_loop_end (loop, n, pblock);
2587 /* Restore the initial offsets. */
2588 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2590 if ((ss->useflags & 2) == 0)
2591 continue;
2593 if (ss->type != GFC_SS_SECTION
2594 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2595 && ss->type != GFC_SS_COMPONENT)
2596 continue;
2598 ss->data.info.offset = ss->data.info.saved_offset;
2601 /* Restart all the inner loops we just finished. */
2602 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
2604 n = loop->order[dim];
2606 gfc_start_block (&loop->code[n]);
2608 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
2610 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
2613 /* Start a block for the secondary copying code. */
2614 gfc_start_block (body);
2618 /* Calculate the upper bound of an array section. */
2620 static tree
2621 gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
2623 int dim;
2624 gfc_expr *end;
2625 tree desc;
2626 tree bound;
2627 gfc_se se;
2628 gfc_ss_info *info;
2630 gcc_assert (ss->type == GFC_SS_SECTION);
2632 info = &ss->data.info;
2633 dim = info->dim[n];
2635 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2636 /* We'll calculate the upper bound once we have access to the
2637 vector's descriptor. */
2638 return NULL;
2640 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2641 desc = info->descriptor;
2642 end = info->ref->u.ar.end[dim];
2644 if (end)
2646 /* The upper bound was specified. */
2647 gfc_init_se (&se, NULL);
2648 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2649 gfc_add_block_to_block (pblock, &se.pre);
2650 bound = se.expr;
2652 else
2654 /* No upper bound was specified, so use the bound of the array. */
2655 bound = gfc_conv_array_ubound (desc, dim);
2658 return bound;
2662 /* Calculate the lower bound of an array section. */
2664 static void
2665 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
2667 gfc_expr *start;
2668 gfc_expr *end;
2669 gfc_expr *stride;
2670 tree desc;
2671 gfc_se se;
2672 gfc_ss_info *info;
2673 int dim;
2675 gcc_assert (ss->type == GFC_SS_SECTION);
2677 info = &ss->data.info;
2678 dim = info->dim[n];
2680 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2682 /* We use a zero-based index to access the vector. */
2683 info->start[n] = gfc_index_zero_node;
2684 info->end[n] = gfc_index_zero_node;
2685 info->stride[n] = gfc_index_one_node;
2686 return;
2689 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2690 desc = info->descriptor;
2691 start = info->ref->u.ar.start[dim];
2692 end = info->ref->u.ar.end[dim];
2693 stride = info->ref->u.ar.stride[dim];
2695 /* Calculate the start of the range. For vector subscripts this will
2696 be the range of the vector. */
2697 if (start)
2699 /* Specified section start. */
2700 gfc_init_se (&se, NULL);
2701 gfc_conv_expr_type (&se, start, gfc_array_index_type);
2702 gfc_add_block_to_block (&loop->pre, &se.pre);
2703 info->start[n] = se.expr;
2705 else
2707 /* No lower bound specified so use the bound of the array. */
2708 info->start[n] = gfc_conv_array_lbound (desc, dim);
2710 info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
2712 /* Similarly calculate the end. Although this is not used in the
2713 scalarizer, it is needed when checking bounds and where the end
2714 is an expression with side-effects. */
2715 if (end)
2717 /* Specified section start. */
2718 gfc_init_se (&se, NULL);
2719 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2720 gfc_add_block_to_block (&loop->pre, &se.pre);
2721 info->end[n] = se.expr;
2723 else
2725 /* No upper bound specified so use the bound of the array. */
2726 info->end[n] = gfc_conv_array_ubound (desc, dim);
2728 info->end[n] = gfc_evaluate_now (info->end[n], &loop->pre);
2730 /* Calculate the stride. */
2731 if (stride == NULL)
2732 info->stride[n] = gfc_index_one_node;
2733 else
2735 gfc_init_se (&se, NULL);
2736 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
2737 gfc_add_block_to_block (&loop->pre, &se.pre);
2738 info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
2743 /* Calculates the range start and stride for a SS chain. Also gets the
2744 descriptor and data pointer. The range of vector subscripts is the size
2745 of the vector. Array bounds are also checked. */
2747 void
2748 gfc_conv_ss_startstride (gfc_loopinfo * loop)
2750 int n;
2751 tree tmp;
2752 gfc_ss *ss;
2753 tree desc;
2755 loop->dimen = 0;
2756 /* Determine the rank of the loop. */
2757 for (ss = loop->ss;
2758 ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
2760 switch (ss->type)
2762 case GFC_SS_SECTION:
2763 case GFC_SS_CONSTRUCTOR:
2764 case GFC_SS_FUNCTION:
2765 case GFC_SS_COMPONENT:
2766 loop->dimen = ss->data.info.dimen;
2767 break;
2769 /* As usual, lbound and ubound are exceptions!. */
2770 case GFC_SS_INTRINSIC:
2771 switch (ss->expr->value.function.isym->id)
2773 case GFC_ISYM_LBOUND:
2774 case GFC_ISYM_UBOUND:
2775 loop->dimen = ss->data.info.dimen;
2777 default:
2778 break;
2781 default:
2782 break;
2786 if (loop->dimen == 0)
2787 gfc_todo_error ("Unable to determine rank of expression");
2790 /* Loop over all the SS in the chain. */
2791 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2793 if (ss->expr && ss->expr->shape && !ss->shape)
2794 ss->shape = ss->expr->shape;
2796 switch (ss->type)
2798 case GFC_SS_SECTION:
2799 /* Get the descriptor for the array. */
2800 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
2802 for (n = 0; n < ss->data.info.dimen; n++)
2803 gfc_conv_section_startstride (loop, ss, n);
2804 break;
2806 case GFC_SS_INTRINSIC:
2807 switch (ss->expr->value.function.isym->id)
2809 /* Fall through to supply start and stride. */
2810 case GFC_ISYM_LBOUND:
2811 case GFC_ISYM_UBOUND:
2812 break;
2813 default:
2814 continue;
2817 case GFC_SS_CONSTRUCTOR:
2818 case GFC_SS_FUNCTION:
2819 for (n = 0; n < ss->data.info.dimen; n++)
2821 ss->data.info.start[n] = gfc_index_zero_node;
2822 ss->data.info.end[n] = gfc_index_zero_node;
2823 ss->data.info.stride[n] = gfc_index_one_node;
2825 break;
2827 default:
2828 break;
2832 /* The rest is just runtime bound checking. */
2833 if (flag_bounds_check)
2835 stmtblock_t block;
2836 tree lbound, ubound;
2837 tree end;
2838 tree size[GFC_MAX_DIMENSIONS];
2839 tree stride_pos, stride_neg, non_zerosized, tmp2;
2840 gfc_ss_info *info;
2841 char *msg;
2842 int dim;
2844 gfc_start_block (&block);
2846 for (n = 0; n < loop->dimen; n++)
2847 size[n] = NULL_TREE;
2849 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2851 if (ss->type != GFC_SS_SECTION)
2852 continue;
2854 /* TODO: range checking for mapped dimensions. */
2855 info = &ss->data.info;
2857 /* This code only checks ranges. Elemental and vector
2858 dimensions are checked later. */
2859 for (n = 0; n < loop->dimen; n++)
2861 bool check_upper;
2863 dim = info->dim[n];
2864 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
2865 continue;
2867 if (n == info->ref->u.ar.dimen - 1
2868 && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
2869 || info->ref->u.ar.as->cp_was_assumed))
2870 check_upper = false;
2871 else
2872 check_upper = true;
2874 /* Zero stride is not allowed. */
2875 tmp = fold_build2 (EQ_EXPR, boolean_type_node, info->stride[n],
2876 gfc_index_zero_node);
2877 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
2878 "of array '%s'", info->dim[n]+1,
2879 ss->expr->symtree->name);
2880 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg);
2881 gfc_free (msg);
2883 desc = ss->data.info.descriptor;
2885 /* This is the run-time equivalent of resolve.c's
2886 check_dimension(). The logical is more readable there
2887 than it is here, with all the trees. */
2888 lbound = gfc_conv_array_lbound (desc, dim);
2889 end = info->end[n];
2890 if (check_upper)
2891 ubound = gfc_conv_array_ubound (desc, dim);
2892 else
2893 ubound = NULL;
2895 /* non_zerosized is true when the selected range is not
2896 empty. */
2897 stride_pos = fold_build2 (GT_EXPR, boolean_type_node,
2898 info->stride[n], gfc_index_zero_node);
2899 tmp = fold_build2 (LE_EXPR, boolean_type_node, info->start[n],
2900 end);
2901 stride_pos = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2902 stride_pos, tmp);
2904 stride_neg = fold_build2 (LT_EXPR, boolean_type_node,
2905 info->stride[n], gfc_index_zero_node);
2906 tmp = fold_build2 (GE_EXPR, boolean_type_node, info->start[n],
2907 end);
2908 stride_neg = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2909 stride_neg, tmp);
2910 non_zerosized = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
2911 stride_pos, stride_neg);
2913 /* Check the start of the range against the lower and upper
2914 bounds of the array, if the range is not empty. */
2915 tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
2916 lbound);
2917 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2918 non_zerosized, tmp);
2919 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
2920 " exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
2921 info->dim[n]+1, ss->expr->symtree->name);
2922 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
2923 fold_convert (long_integer_type_node,
2924 info->start[n]),
2925 fold_convert (long_integer_type_node,
2926 lbound));
2927 gfc_free (msg);
2929 if (check_upper)
2931 tmp = fold_build2 (GT_EXPR, boolean_type_node,
2932 info->start[n], ubound);
2933 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2934 non_zerosized, tmp);
2935 asprintf (&msg, "%s, upper bound of dimension %d of array "
2936 "'%s' exceeded, %%ld is greater than %%ld",
2937 gfc_msg_fault, info->dim[n]+1,
2938 ss->expr->symtree->name);
2939 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
2940 fold_convert (long_integer_type_node, info->start[n]),
2941 fold_convert (long_integer_type_node, ubound));
2942 gfc_free (msg);
2945 /* Compute the last element of the range, which is not
2946 necessarily "end" (think 0:5:3, which doesn't contain 5)
2947 and check it against both lower and upper bounds. */
2948 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
2949 info->start[n]);
2950 tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
2951 info->stride[n]);
2952 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
2953 tmp2);
2955 tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
2956 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2957 non_zerosized, tmp);
2958 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
2959 " exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
2960 info->dim[n]+1, ss->expr->symtree->name);
2961 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
2962 fold_convert (long_integer_type_node,
2963 tmp2),
2964 fold_convert (long_integer_type_node,
2965 lbound));
2966 gfc_free (msg);
2968 if (check_upper)
2970 tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
2971 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2972 non_zerosized, tmp);
2973 asprintf (&msg, "%s, upper bound of dimension %d of array "
2974 "'%s' exceeded, %%ld is greater than %%ld",
2975 gfc_msg_fault, info->dim[n]+1,
2976 ss->expr->symtree->name);
2977 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
2978 fold_convert (long_integer_type_node, tmp2),
2979 fold_convert (long_integer_type_node, ubound));
2980 gfc_free (msg);
2983 /* Check the section sizes match. */
2984 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
2985 info->start[n]);
2986 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
2987 info->stride[n]);
2988 /* We remember the size of the first section, and check all the
2989 others against this. */
2990 if (size[n])
2992 tree tmp3
2993 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
2994 asprintf (&msg, "%s, size mismatch for dimension %d "
2995 "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
2996 info->dim[n]+1, ss->expr->symtree->name);
2997 gfc_trans_runtime_check (tmp3, &block, &ss->expr->where, msg,
2998 fold_convert (long_integer_type_node, tmp),
2999 fold_convert (long_integer_type_node, size[n]));
3000 gfc_free (msg);
3002 else
3003 size[n] = gfc_evaluate_now (tmp, &block);
3007 tmp = gfc_finish_block (&block);
3008 gfc_add_expr_to_block (&loop->pre, tmp);
3013 /* Return true if the two SS could be aliased, i.e. both point to the same data
3014 object. */
3015 /* TODO: resolve aliases based on frontend expressions. */
3017 static int
3018 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
3020 gfc_ref *lref;
3021 gfc_ref *rref;
3022 gfc_symbol *lsym;
3023 gfc_symbol *rsym;
3025 lsym = lss->expr->symtree->n.sym;
3026 rsym = rss->expr->symtree->n.sym;
3027 if (gfc_symbols_could_alias (lsym, rsym))
3028 return 1;
3030 if (rsym->ts.type != BT_DERIVED
3031 && lsym->ts.type != BT_DERIVED)
3032 return 0;
3034 /* For derived types we must check all the component types. We can ignore
3035 array references as these will have the same base type as the previous
3036 component ref. */
3037 for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
3039 if (lref->type != REF_COMPONENT)
3040 continue;
3042 if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
3043 return 1;
3045 for (rref = rss->expr->ref; rref != rss->data.info.ref;
3046 rref = rref->next)
3048 if (rref->type != REF_COMPONENT)
3049 continue;
3051 if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
3052 return 1;
3056 for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
3058 if (rref->type != REF_COMPONENT)
3059 break;
3061 if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
3062 return 1;
3065 return 0;
3069 /* Resolve array data dependencies. Creates a temporary if required. */
3070 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
3071 dependency.c. */
3073 void
3074 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
3075 gfc_ss * rss)
3077 gfc_ss *ss;
3078 gfc_ref *lref;
3079 gfc_ref *rref;
3080 gfc_ref *aref;
3081 int nDepend = 0;
3082 int temp_dim = 0;
3084 loop->temp_ss = NULL;
3085 aref = dest->data.info.ref;
3086 temp_dim = 0;
3088 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
3090 if (ss->type != GFC_SS_SECTION)
3091 continue;
3093 if (gfc_could_be_alias (dest, ss)
3094 || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3096 nDepend = 1;
3097 break;
3100 if (dest->expr->symtree->n.sym == ss->expr->symtree->n.sym)
3102 lref = dest->expr->ref;
3103 rref = ss->expr->ref;
3105 nDepend = gfc_dep_resolver (lref, rref);
3106 if (nDepend == 1)
3107 break;
3108 #if 0
3109 /* TODO : loop shifting. */
3110 if (nDepend == 1)
3112 /* Mark the dimensions for LOOP SHIFTING */
3113 for (n = 0; n < loop->dimen; n++)
3115 int dim = dest->data.info.dim[n];
3117 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3118 depends[n] = 2;
3119 else if (! gfc_is_same_range (&lref->u.ar,
3120 &rref->u.ar, dim, 0))
3121 depends[n] = 1;
3124 /* Put all the dimensions with dependencies in the
3125 innermost loops. */
3126 dim = 0;
3127 for (n = 0; n < loop->dimen; n++)
3129 gcc_assert (loop->order[n] == n);
3130 if (depends[n])
3131 loop->order[dim++] = n;
3133 temp_dim = dim;
3134 for (n = 0; n < loop->dimen; n++)
3136 if (! depends[n])
3137 loop->order[dim++] = n;
3140 gcc_assert (dim == loop->dimen);
3141 break;
3143 #endif
3147 if (nDepend == 1)
3149 tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
3150 if (GFC_ARRAY_TYPE_P (base_type)
3151 || GFC_DESCRIPTOR_TYPE_P (base_type))
3152 base_type = gfc_get_element_type (base_type);
3153 loop->temp_ss = gfc_get_ss ();
3154 loop->temp_ss->type = GFC_SS_TEMP;
3155 loop->temp_ss->data.temp.type = base_type;
3156 loop->temp_ss->string_length = dest->string_length;
3157 loop->temp_ss->data.temp.dimen = loop->dimen;
3158 loop->temp_ss->next = gfc_ss_terminator;
3159 gfc_add_ss_to_loop (loop, loop->temp_ss);
3161 else
3162 loop->temp_ss = NULL;
3166 /* Initialize the scalarization loop. Creates the loop variables. Determines
3167 the range of the loop variables. Creates a temporary if required.
3168 Calculates how to transform from loop variables to array indices for each
3169 expression. Also generates code for scalar expressions which have been
3170 moved outside the loop. */
3172 void
3173 gfc_conv_loop_setup (gfc_loopinfo * loop)
3175 int n;
3176 int dim;
3177 gfc_ss_info *info;
3178 gfc_ss_info *specinfo;
3179 gfc_ss *ss;
3180 tree tmp;
3181 tree len;
3182 gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
3183 bool dynamic[GFC_MAX_DIMENSIONS];
3184 gfc_constructor *c;
3185 mpz_t *cshape;
3186 mpz_t i;
3188 mpz_init (i);
3189 for (n = 0; n < loop->dimen; n++)
3191 loopspec[n] = NULL;
3192 dynamic[n] = false;
3193 /* We use one SS term, and use that to determine the bounds of the
3194 loop for this dimension. We try to pick the simplest term. */
3195 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3197 if (ss->shape)
3199 /* The frontend has worked out the size for us. */
3200 loopspec[n] = ss;
3201 continue;
3204 if (ss->type == GFC_SS_CONSTRUCTOR)
3206 /* An unknown size constructor will always be rank one.
3207 Higher rank constructors will either have known shape,
3208 or still be wrapped in a call to reshape. */
3209 gcc_assert (loop->dimen == 1);
3211 /* Always prefer to use the constructor bounds if the size
3212 can be determined at compile time. Prefer not to otherwise,
3213 since the general case involves realloc, and it's better to
3214 avoid that overhead if possible. */
3215 c = ss->expr->value.constructor;
3216 dynamic[n] = gfc_get_array_constructor_size (&i, c);
3217 if (!dynamic[n] || !loopspec[n])
3218 loopspec[n] = ss;
3219 continue;
3222 /* TODO: Pick the best bound if we have a choice between a
3223 function and something else. */
3224 if (ss->type == GFC_SS_FUNCTION)
3226 loopspec[n] = ss;
3227 continue;
3230 if (ss->type != GFC_SS_SECTION)
3231 continue;
3233 if (loopspec[n])
3234 specinfo = &loopspec[n]->data.info;
3235 else
3236 specinfo = NULL;
3237 info = &ss->data.info;
3239 if (!specinfo)
3240 loopspec[n] = ss;
3241 /* Criteria for choosing a loop specifier (most important first):
3242 doesn't need realloc
3243 stride of one
3244 known stride
3245 known lower bound
3246 known upper bound
3248 else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
3249 loopspec[n] = ss;
3250 else if (integer_onep (info->stride[n])
3251 && !integer_onep (specinfo->stride[n]))
3252 loopspec[n] = ss;
3253 else if (INTEGER_CST_P (info->stride[n])
3254 && !INTEGER_CST_P (specinfo->stride[n]))
3255 loopspec[n] = ss;
3256 else if (INTEGER_CST_P (info->start[n])
3257 && !INTEGER_CST_P (specinfo->start[n]))
3258 loopspec[n] = ss;
3259 /* We don't work out the upper bound.
3260 else if (INTEGER_CST_P (info->finish[n])
3261 && ! INTEGER_CST_P (specinfo->finish[n]))
3262 loopspec[n] = ss; */
3265 if (!loopspec[n])
3266 gfc_todo_error ("Unable to find scalarization loop specifier");
3268 info = &loopspec[n]->data.info;
3270 /* Set the extents of this range. */
3271 cshape = loopspec[n]->shape;
3272 if (cshape && INTEGER_CST_P (info->start[n])
3273 && INTEGER_CST_P (info->stride[n]))
3275 loop->from[n] = info->start[n];
3276 mpz_set (i, cshape[n]);
3277 mpz_sub_ui (i, i, 1);
3278 /* To = from + (size - 1) * stride. */
3279 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
3280 if (!integer_onep (info->stride[n]))
3281 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3282 tmp, info->stride[n]);
3283 loop->to[n] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3284 loop->from[n], tmp);
3286 else
3288 loop->from[n] = info->start[n];
3289 switch (loopspec[n]->type)
3291 case GFC_SS_CONSTRUCTOR:
3292 /* The upper bound is calculated when we expand the
3293 constructor. */
3294 gcc_assert (loop->to[n] == NULL_TREE);
3295 break;
3297 case GFC_SS_SECTION:
3298 loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
3299 &loop->pre);
3300 break;
3302 case GFC_SS_FUNCTION:
3303 /* The loop bound will be set when we generate the call. */
3304 gcc_assert (loop->to[n] == NULL_TREE);
3305 break;
3307 default:
3308 gcc_unreachable ();
3312 /* Transform everything so we have a simple incrementing variable. */
3313 if (integer_onep (info->stride[n]))
3314 info->delta[n] = gfc_index_zero_node;
3315 else
3317 /* Set the delta for this section. */
3318 info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
3319 /* Number of iterations is (end - start + step) / step.
3320 with start = 0, this simplifies to
3321 last = end / step;
3322 for (i = 0; i<=last; i++){...}; */
3323 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3324 loop->to[n], loop->from[n]);
3325 tmp = fold_build2 (TRUNC_DIV_EXPR, gfc_array_index_type,
3326 tmp, info->stride[n]);
3327 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
3328 /* Make the loop variable start at 0. */
3329 loop->from[n] = gfc_index_zero_node;
3333 /* Add all the scalar code that can be taken out of the loops.
3334 This may include calculating the loop bounds, so do it before
3335 allocating the temporary. */
3336 gfc_add_loop_ss_code (loop, loop->ss, false);
3338 /* If we want a temporary then create it. */
3339 if (loop->temp_ss != NULL)
3341 gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
3342 tmp = loop->temp_ss->data.temp.type;
3343 len = loop->temp_ss->string_length;
3344 n = loop->temp_ss->data.temp.dimen;
3345 memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
3346 loop->temp_ss->type = GFC_SS_SECTION;
3347 loop->temp_ss->data.info.dimen = n;
3348 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
3349 &loop->temp_ss->data.info, tmp, false, true,
3350 false);
3353 for (n = 0; n < loop->temp_dim; n++)
3354 loopspec[loop->order[n]] = NULL;
3356 mpz_clear (i);
3358 /* For array parameters we don't have loop variables, so don't calculate the
3359 translations. */
3360 if (loop->array_parameter)
3361 return;
3363 /* Calculate the translation from loop variables to array indices. */
3364 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3366 if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT)
3367 continue;
3369 info = &ss->data.info;
3371 for (n = 0; n < info->dimen; n++)
3373 dim = info->dim[n];
3375 /* If we are specifying the range the delta is already set. */
3376 if (loopspec[n] != ss)
3378 /* Calculate the offset relative to the loop variable.
3379 First multiply by the stride. */
3380 tmp = loop->from[n];
3381 if (!integer_onep (info->stride[n]))
3382 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3383 tmp, info->stride[n]);
3385 /* Then subtract this from our starting value. */
3386 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3387 info->start[n], tmp);
3389 info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
3396 /* Fills in an array descriptor, and returns the size of the array. The size
3397 will be a simple_val, ie a variable or a constant. Also calculates the
3398 offset of the base. Returns the size of the array.
3400 stride = 1;
3401 offset = 0;
3402 for (n = 0; n < rank; n++)
3404 a.lbound[n] = specified_lower_bound;
3405 offset = offset + a.lbond[n] * stride;
3406 size = 1 - lbound;
3407 a.ubound[n] = specified_upper_bound;
3408 a.stride[n] = stride;
3409 size = ubound + size; //size = ubound + 1 - lbound
3410 stride = stride * size;
3412 return (stride);
3413 } */
3414 /*GCC ARRAYS*/
3416 static tree
3417 gfc_array_init_size (tree descriptor, int rank, tree * poffset,
3418 gfc_expr ** lower, gfc_expr ** upper,
3419 stmtblock_t * pblock)
3421 tree type;
3422 tree tmp;
3423 tree size;
3424 tree offset;
3425 tree stride;
3426 tree cond;
3427 tree or_expr;
3428 tree thencase;
3429 tree elsecase;
3430 tree var;
3431 stmtblock_t thenblock;
3432 stmtblock_t elseblock;
3433 gfc_expr *ubound;
3434 gfc_se se;
3435 int n;
3437 type = TREE_TYPE (descriptor);
3439 stride = gfc_index_one_node;
3440 offset = gfc_index_zero_node;
3442 /* Set the dtype. */
3443 tmp = gfc_conv_descriptor_dtype (descriptor);
3444 gfc_add_modify_expr (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
3446 or_expr = NULL_TREE;
3448 for (n = 0; n < rank; n++)
3450 /* We have 3 possibilities for determining the size of the array:
3451 lower == NULL => lbound = 1, ubound = upper[n]
3452 upper[n] = NULL => lbound = 1, ubound = lower[n]
3453 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
3454 ubound = upper[n];
3456 /* Set lower bound. */
3457 gfc_init_se (&se, NULL);
3458 if (lower == NULL)
3459 se.expr = gfc_index_one_node;
3460 else
3462 gcc_assert (lower[n]);
3463 if (ubound)
3465 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
3466 gfc_add_block_to_block (pblock, &se.pre);
3468 else
3470 se.expr = gfc_index_one_node;
3471 ubound = lower[n];
3474 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
3475 gfc_add_modify_expr (pblock, tmp, se.expr);
3477 /* Work out the offset for this component. */
3478 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
3479 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3481 /* Start the calculation for the size of this dimension. */
3482 size = build2 (MINUS_EXPR, gfc_array_index_type,
3483 gfc_index_one_node, se.expr);
3485 /* Set upper bound. */
3486 gfc_init_se (&se, NULL);
3487 gcc_assert (ubound);
3488 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
3489 gfc_add_block_to_block (pblock, &se.pre);
3491 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
3492 gfc_add_modify_expr (pblock, tmp, se.expr);
3494 /* Store the stride. */
3495 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
3496 gfc_add_modify_expr (pblock, tmp, stride);
3498 /* Calculate the size of this dimension. */
3499 size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
3501 /* Check whether the size for this dimension is negative. */
3502 cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3503 gfc_index_zero_node);
3504 if (n == 0)
3505 or_expr = cond;
3506 else
3507 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
3509 /* Multiply the stride by the number of elements in this dimension. */
3510 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, size);
3511 stride = gfc_evaluate_now (stride, pblock);
3514 /* The stride is the number of elements in the array, so multiply by the
3515 size of an element to get the total size. */
3516 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3517 size = fold_build2 (MULT_EXPR, gfc_array_index_type, stride,
3518 fold_convert (gfc_array_index_type, tmp));
3520 if (poffset != NULL)
3522 offset = gfc_evaluate_now (offset, pblock);
3523 *poffset = offset;
3526 if (integer_zerop (or_expr))
3527 return size;
3528 if (integer_onep (or_expr))
3529 return gfc_index_zero_node;
3531 var = gfc_create_var (TREE_TYPE (size), "size");
3532 gfc_start_block (&thenblock);
3533 gfc_add_modify_expr (&thenblock, var, gfc_index_zero_node);
3534 thencase = gfc_finish_block (&thenblock);
3536 gfc_start_block (&elseblock);
3537 gfc_add_modify_expr (&elseblock, var, size);
3538 elsecase = gfc_finish_block (&elseblock);
3540 tmp = gfc_evaluate_now (or_expr, pblock);
3541 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
3542 gfc_add_expr_to_block (pblock, tmp);
3544 return var;
3548 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
3549 the work for an ALLOCATE statement. */
3550 /*GCC ARRAYS*/
3552 bool
3553 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
3555 tree tmp;
3556 tree pointer;
3557 tree offset;
3558 tree size;
3559 gfc_expr **lower;
3560 gfc_expr **upper;
3561 gfc_ref *ref, *prev_ref = NULL;
3562 bool allocatable_array;
3564 ref = expr->ref;
3566 /* Find the last reference in the chain. */
3567 while (ref && ref->next != NULL)
3569 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
3570 prev_ref = ref;
3571 ref = ref->next;
3574 if (ref == NULL || ref->type != REF_ARRAY)
3575 return false;
3577 if (!prev_ref)
3578 allocatable_array = expr->symtree->n.sym->attr.allocatable;
3579 else
3580 allocatable_array = prev_ref->u.c.component->allocatable;
3582 /* Figure out the size of the array. */
3583 switch (ref->u.ar.type)
3585 case AR_ELEMENT:
3586 lower = NULL;
3587 upper = ref->u.ar.start;
3588 break;
3590 case AR_FULL:
3591 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
3593 lower = ref->u.ar.as->lower;
3594 upper = ref->u.ar.as->upper;
3595 break;
3597 case AR_SECTION:
3598 lower = ref->u.ar.start;
3599 upper = ref->u.ar.end;
3600 break;
3602 default:
3603 gcc_unreachable ();
3604 break;
3607 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
3608 lower, upper, &se->pre);
3610 /* Allocate memory to store the data. */
3611 pointer = gfc_conv_descriptor_data_get (se->expr);
3612 STRIP_NOPS (pointer);
3614 /* The allocate_array variants take the old pointer as first argument. */
3615 if (allocatable_array)
3616 tmp = gfc_allocate_array_with_status (&se->pre, pointer, size, pstat);
3617 else
3618 tmp = gfc_allocate_with_status (&se->pre, size, pstat);
3619 tmp = build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
3620 gfc_add_expr_to_block (&se->pre, tmp);
3622 tmp = gfc_conv_descriptor_offset (se->expr);
3623 gfc_add_modify_expr (&se->pre, tmp, offset);
3625 if (expr->ts.type == BT_DERIVED
3626 && expr->ts.derived->attr.alloc_comp)
3628 tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
3629 ref->u.ar.as->rank);
3630 gfc_add_expr_to_block (&se->pre, tmp);
3633 return true;
3637 /* Deallocate an array variable. Also used when an allocated variable goes
3638 out of scope. */
3639 /*GCC ARRAYS*/
3641 tree
3642 gfc_array_deallocate (tree descriptor, tree pstat)
3644 tree var;
3645 tree tmp;
3646 stmtblock_t block;
3648 gfc_start_block (&block);
3649 /* Get a pointer to the data. */
3650 var = gfc_conv_descriptor_data_get (descriptor);
3651 STRIP_NOPS (var);
3653 /* Parameter is the address of the data component. */
3654 tmp = gfc_deallocate_with_status (var, pstat, false);
3655 gfc_add_expr_to_block (&block, tmp);
3657 /* Zero the data pointer. */
3658 tmp = build2 (MODIFY_EXPR, void_type_node,
3659 var, build_int_cst (TREE_TYPE (var), 0));
3660 gfc_add_expr_to_block (&block, tmp);
3662 return gfc_finish_block (&block);
3666 /* Create an array constructor from an initialization expression.
3667 We assume the frontend already did any expansions and conversions. */
3669 tree
3670 gfc_conv_array_initializer (tree type, gfc_expr * expr)
3672 gfc_constructor *c;
3673 tree tmp;
3674 mpz_t maxval;
3675 gfc_se se;
3676 HOST_WIDE_INT hi;
3677 unsigned HOST_WIDE_INT lo;
3678 tree index, range;
3679 VEC(constructor_elt,gc) *v = NULL;
3681 switch (expr->expr_type)
3683 case EXPR_CONSTANT:
3684 case EXPR_STRUCTURE:
3685 /* A single scalar or derived type value. Create an array with all
3686 elements equal to that value. */
3687 gfc_init_se (&se, NULL);
3689 if (expr->expr_type == EXPR_CONSTANT)
3690 gfc_conv_constant (&se, expr);
3691 else
3692 gfc_conv_structure (&se, expr, 1);
3694 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
3695 gcc_assert (tmp && INTEGER_CST_P (tmp));
3696 hi = TREE_INT_CST_HIGH (tmp);
3697 lo = TREE_INT_CST_LOW (tmp);
3698 lo++;
3699 if (lo == 0)
3700 hi++;
3701 /* This will probably eat buckets of memory for large arrays. */
3702 while (hi != 0 || lo != 0)
3704 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
3705 if (lo == 0)
3706 hi--;
3707 lo--;
3709 break;
3711 case EXPR_ARRAY:
3712 /* Create a vector of all the elements. */
3713 for (c = expr->value.constructor; c; c = c->next)
3715 if (c->iterator)
3717 /* Problems occur when we get something like
3718 integer :: a(lots) = (/(i, i=1,lots)/) */
3719 /* TODO: Unexpanded array initializers. */
3720 internal_error
3721 ("Possible frontend bug: array constructor not expanded");
3723 if (mpz_cmp_si (c->n.offset, 0) != 0)
3724 index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3725 else
3726 index = NULL_TREE;
3727 mpz_init (maxval);
3728 if (mpz_cmp_si (c->repeat, 0) != 0)
3730 tree tmp1, tmp2;
3732 mpz_set (maxval, c->repeat);
3733 mpz_add (maxval, c->n.offset, maxval);
3734 mpz_sub_ui (maxval, maxval, 1);
3735 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3736 if (mpz_cmp_si (c->n.offset, 0) != 0)
3738 mpz_add_ui (maxval, c->n.offset, 1);
3739 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3741 else
3742 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3744 range = build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
3746 else
3747 range = NULL;
3748 mpz_clear (maxval);
3750 gfc_init_se (&se, NULL);
3751 switch (c->expr->expr_type)
3753 case EXPR_CONSTANT:
3754 gfc_conv_constant (&se, c->expr);
3755 if (range == NULL_TREE)
3756 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3757 else
3759 if (index != NULL_TREE)
3760 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3761 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
3763 break;
3765 case EXPR_STRUCTURE:
3766 gfc_conv_structure (&se, c->expr, 1);
3767 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3768 break;
3770 default:
3771 gcc_unreachable ();
3774 break;
3776 case EXPR_NULL:
3777 return gfc_build_null_descriptor (type);
3779 default:
3780 gcc_unreachable ();
3783 /* Create a constructor from the list of elements. */
3784 tmp = build_constructor (type, v);
3785 TREE_CONSTANT (tmp) = 1;
3786 TREE_INVARIANT (tmp) = 1;
3787 return tmp;
3791 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
3792 returns the size (in elements) of the array. */
3794 static tree
3795 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
3796 stmtblock_t * pblock)
3798 gfc_array_spec *as;
3799 tree size;
3800 tree stride;
3801 tree offset;
3802 tree ubound;
3803 tree lbound;
3804 tree tmp;
3805 gfc_se se;
3807 int dim;
3809 as = sym->as;
3811 size = gfc_index_one_node;
3812 offset = gfc_index_zero_node;
3813 for (dim = 0; dim < as->rank; dim++)
3815 /* Evaluate non-constant array bound expressions. */
3816 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
3817 if (as->lower[dim] && !INTEGER_CST_P (lbound))
3819 gfc_init_se (&se, NULL);
3820 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
3821 gfc_add_block_to_block (pblock, &se.pre);
3822 gfc_add_modify_expr (pblock, lbound, se.expr);
3824 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
3825 if (as->upper[dim] && !INTEGER_CST_P (ubound))
3827 gfc_init_se (&se, NULL);
3828 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
3829 gfc_add_block_to_block (pblock, &se.pre);
3830 gfc_add_modify_expr (pblock, ubound, se.expr);
3832 /* The offset of this dimension. offset = offset - lbound * stride. */
3833 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, size);
3834 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3836 /* The size of this dimension, and the stride of the next. */
3837 if (dim + 1 < as->rank)
3838 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
3839 else
3840 stride = GFC_TYPE_ARRAY_SIZE (type);
3842 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
3844 /* Calculate stride = size * (ubound + 1 - lbound). */
3845 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3846 gfc_index_one_node, lbound);
3847 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp);
3848 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
3849 if (stride)
3850 gfc_add_modify_expr (pblock, stride, tmp);
3851 else
3852 stride = gfc_evaluate_now (tmp, pblock);
3854 /* Make sure that negative size arrays are translated
3855 to being zero size. */
3856 tmp = build2 (GE_EXPR, boolean_type_node,
3857 stride, gfc_index_zero_node);
3858 tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
3859 stride, gfc_index_zero_node);
3860 gfc_add_modify_expr (pblock, stride, tmp);
3863 size = stride;
3866 gfc_trans_vla_type_sizes (sym, pblock);
3868 *poffset = offset;
3869 return size;
3873 /* Generate code to initialize/allocate an array variable. */
3875 tree
3876 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
3878 stmtblock_t block;
3879 tree type;
3880 tree tmp;
3881 tree size;
3882 tree offset;
3883 bool onstack;
3885 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
3887 /* Do nothing for USEd variables. */
3888 if (sym->attr.use_assoc)
3889 return fnbody;
3891 type = TREE_TYPE (decl);
3892 gcc_assert (GFC_ARRAY_TYPE_P (type));
3893 onstack = TREE_CODE (type) != POINTER_TYPE;
3895 gfc_start_block (&block);
3897 /* Evaluate character string length. */
3898 if (sym->ts.type == BT_CHARACTER
3899 && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3901 gfc_conv_string_length (sym->ts.cl, &block);
3903 gfc_trans_vla_type_sizes (sym, &block);
3905 /* Emit a DECL_EXPR for this variable, which will cause the
3906 gimplifier to allocate storage, and all that good stuff. */
3907 tmp = build1 (DECL_EXPR, TREE_TYPE (decl), decl);
3908 gfc_add_expr_to_block (&block, tmp);
3911 if (onstack)
3913 gfc_add_expr_to_block (&block, fnbody);
3914 return gfc_finish_block (&block);
3917 type = TREE_TYPE (type);
3919 gcc_assert (!sym->attr.use_assoc);
3920 gcc_assert (!TREE_STATIC (decl));
3921 gcc_assert (!sym->module);
3923 if (sym->ts.type == BT_CHARACTER
3924 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3925 gfc_conv_string_length (sym->ts.cl, &block);
3927 size = gfc_trans_array_bounds (type, sym, &offset, &block);
3929 /* Don't actually allocate space for Cray Pointees. */
3930 if (sym->attr.cray_pointee)
3932 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3933 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
3934 gfc_add_expr_to_block (&block, fnbody);
3935 return gfc_finish_block (&block);
3938 /* The size is the number of elements in the array, so multiply by the
3939 size of an element to get the total size. */
3940 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3941 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
3942 fold_convert (gfc_array_index_type, tmp));
3944 /* Allocate memory to hold the data. */
3945 tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
3946 gfc_add_modify_expr (&block, decl, tmp);
3948 /* Set offset of the array. */
3949 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3950 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
3953 /* Automatic arrays should not have initializers. */
3954 gcc_assert (!sym->value);
3956 gfc_add_expr_to_block (&block, fnbody);
3958 /* Free the temporary. */
3959 tmp = gfc_call_free (convert (pvoid_type_node, decl));
3960 gfc_add_expr_to_block (&block, tmp);
3962 return gfc_finish_block (&block);
3966 /* Generate entry and exit code for g77 calling convention arrays. */
3968 tree
3969 gfc_trans_g77_array (gfc_symbol * sym, tree body)
3971 tree parm;
3972 tree type;
3973 locus loc;
3974 tree offset;
3975 tree tmp;
3976 tree stmt;
3977 stmtblock_t block;
3979 gfc_get_backend_locus (&loc);
3980 gfc_set_backend_locus (&sym->declared_at);
3982 /* Descriptor type. */
3983 parm = sym->backend_decl;
3984 type = TREE_TYPE (parm);
3985 gcc_assert (GFC_ARRAY_TYPE_P (type));
3987 gfc_start_block (&block);
3989 if (sym->ts.type == BT_CHARACTER
3990 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
3991 gfc_conv_string_length (sym->ts.cl, &block);
3993 /* Evaluate the bounds of the array. */
3994 gfc_trans_array_bounds (type, sym, &offset, &block);
3996 /* Set the offset. */
3997 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3998 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4000 /* Set the pointer itself if we aren't using the parameter directly. */
4001 if (TREE_CODE (parm) != PARM_DECL)
4003 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
4004 gfc_add_modify_expr (&block, parm, tmp);
4006 stmt = gfc_finish_block (&block);
4008 gfc_set_backend_locus (&loc);
4010 gfc_start_block (&block);
4012 /* Add the initialization code to the start of the function. */
4014 if (sym->attr.optional || sym->attr.not_always_present)
4016 tmp = gfc_conv_expr_present (sym);
4017 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4020 gfc_add_expr_to_block (&block, stmt);
4021 gfc_add_expr_to_block (&block, body);
4023 return gfc_finish_block (&block);
4027 /* Modify the descriptor of an array parameter so that it has the
4028 correct lower bound. Also move the upper bound accordingly.
4029 If the array is not packed, it will be copied into a temporary.
4030 For each dimension we set the new lower and upper bounds. Then we copy the
4031 stride and calculate the offset for this dimension. We also work out
4032 what the stride of a packed array would be, and see it the two match.
4033 If the array need repacking, we set the stride to the values we just
4034 calculated, recalculate the offset and copy the array data.
4035 Code is also added to copy the data back at the end of the function.
4038 tree
4039 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
4041 tree size;
4042 tree type;
4043 tree offset;
4044 locus loc;
4045 stmtblock_t block;
4046 stmtblock_t cleanup;
4047 tree lbound;
4048 tree ubound;
4049 tree dubound;
4050 tree dlbound;
4051 tree dumdesc;
4052 tree tmp;
4053 tree stmt;
4054 tree stride, stride2;
4055 tree stmt_packed;
4056 tree stmt_unpacked;
4057 tree partial;
4058 gfc_se se;
4059 int n;
4060 int checkparm;
4061 int no_repack;
4062 bool optional_arg;
4064 /* Do nothing for pointer and allocatable arrays. */
4065 if (sym->attr.pointer || sym->attr.allocatable)
4066 return body;
4068 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
4069 return gfc_trans_g77_array (sym, body);
4071 gfc_get_backend_locus (&loc);
4072 gfc_set_backend_locus (&sym->declared_at);
4074 /* Descriptor type. */
4075 type = TREE_TYPE (tmpdesc);
4076 gcc_assert (GFC_ARRAY_TYPE_P (type));
4077 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4078 dumdesc = build_fold_indirect_ref (dumdesc);
4079 gfc_start_block (&block);
4081 if (sym->ts.type == BT_CHARACTER
4082 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4083 gfc_conv_string_length (sym->ts.cl, &block);
4085 checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);
4087 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
4088 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
4090 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
4092 /* For non-constant shape arrays we only check if the first dimension
4093 is contiguous. Repacking higher dimensions wouldn't gain us
4094 anything as we still don't know the array stride. */
4095 partial = gfc_create_var (boolean_type_node, "partial");
4096 TREE_USED (partial) = 1;
4097 tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4098 tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
4099 gfc_add_modify_expr (&block, partial, tmp);
4101 else
4103 partial = NULL_TREE;
4106 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
4107 here, however I think it does the right thing. */
4108 if (no_repack)
4110 /* Set the first stride. */
4111 stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4112 stride = gfc_evaluate_now (stride, &block);
4114 tmp = build2 (EQ_EXPR, boolean_type_node, stride, gfc_index_zero_node);
4115 tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
4116 gfc_index_one_node, stride);
4117 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
4118 gfc_add_modify_expr (&block, stride, tmp);
4120 /* Allow the user to disable array repacking. */
4121 stmt_unpacked = NULL_TREE;
4123 else
4125 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
4126 /* A library call to repack the array if necessary. */
4127 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4128 stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
4130 stride = gfc_index_one_node;
4133 /* This is for the case where the array data is used directly without
4134 calling the repack function. */
4135 if (no_repack || partial != NULL_TREE)
4136 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
4137 else
4138 stmt_packed = NULL_TREE;
4140 /* Assign the data pointer. */
4141 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4143 /* Don't repack unknown shape arrays when the first stride is 1. */
4144 tmp = build3 (COND_EXPR, TREE_TYPE (stmt_packed), partial,
4145 stmt_packed, stmt_unpacked);
4147 else
4148 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
4149 gfc_add_modify_expr (&block, tmpdesc, fold_convert (type, tmp));
4151 offset = gfc_index_zero_node;
4152 size = gfc_index_one_node;
4154 /* Evaluate the bounds of the array. */
4155 for (n = 0; n < sym->as->rank; n++)
4157 if (checkparm || !sym->as->upper[n])
4159 /* Get the bounds of the actual parameter. */
4160 dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
4161 dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
4163 else
4165 dubound = NULL_TREE;
4166 dlbound = NULL_TREE;
4169 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
4170 if (!INTEGER_CST_P (lbound))
4172 gfc_init_se (&se, NULL);
4173 gfc_conv_expr_type (&se, sym->as->lower[n],
4174 gfc_array_index_type);
4175 gfc_add_block_to_block (&block, &se.pre);
4176 gfc_add_modify_expr (&block, lbound, se.expr);
4179 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
4180 /* Set the desired upper bound. */
4181 if (sym->as->upper[n])
4183 /* We know what we want the upper bound to be. */
4184 if (!INTEGER_CST_P (ubound))
4186 gfc_init_se (&se, NULL);
4187 gfc_conv_expr_type (&se, sym->as->upper[n],
4188 gfc_array_index_type);
4189 gfc_add_block_to_block (&block, &se.pre);
4190 gfc_add_modify_expr (&block, ubound, se.expr);
4193 /* Check the sizes match. */
4194 if (checkparm)
4196 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
4197 char * msg;
4199 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4200 ubound, lbound);
4201 stride2 = build2 (MINUS_EXPR, gfc_array_index_type,
4202 dubound, dlbound);
4203 tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
4204 asprintf (&msg, "%s for dimension %d of array '%s'",
4205 gfc_msg_bounds, n+1, sym->name);
4206 gfc_trans_runtime_check (tmp, &block, &loc, msg);
4207 gfc_free (msg);
4210 else
4212 /* For assumed shape arrays move the upper bound by the same amount
4213 as the lower bound. */
4214 tmp = build2 (MINUS_EXPR, gfc_array_index_type, dubound, dlbound);
4215 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound);
4216 gfc_add_modify_expr (&block, ubound, tmp);
4218 /* The offset of this dimension. offset = offset - lbound * stride. */
4219 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, stride);
4220 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
4222 /* The size of this dimension, and the stride of the next. */
4223 if (n + 1 < sym->as->rank)
4225 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
4227 if (no_repack || partial != NULL_TREE)
4229 stmt_unpacked =
4230 gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
4233 /* Figure out the stride if not a known constant. */
4234 if (!INTEGER_CST_P (stride))
4236 if (no_repack)
4237 stmt_packed = NULL_TREE;
4238 else
4240 /* Calculate stride = size * (ubound + 1 - lbound). */
4241 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4242 gfc_index_one_node, lbound);
4243 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4244 ubound, tmp);
4245 size = fold_build2 (MULT_EXPR, gfc_array_index_type,
4246 size, tmp);
4247 stmt_packed = size;
4250 /* Assign the stride. */
4251 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4252 tmp = build3 (COND_EXPR, gfc_array_index_type, partial,
4253 stmt_unpacked, stmt_packed);
4254 else
4255 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
4256 gfc_add_modify_expr (&block, stride, tmp);
4259 else
4261 stride = GFC_TYPE_ARRAY_SIZE (type);
4263 if (stride && !INTEGER_CST_P (stride))
4265 /* Calculate size = stride * (ubound + 1 - lbound). */
4266 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4267 gfc_index_one_node, lbound);
4268 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4269 ubound, tmp);
4270 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4271 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
4272 gfc_add_modify_expr (&block, stride, tmp);
4277 /* Set the offset. */
4278 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4279 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4281 gfc_trans_vla_type_sizes (sym, &block);
4283 stmt = gfc_finish_block (&block);
4285 gfc_start_block (&block);
4287 /* Only do the entry/initialization code if the arg is present. */
4288 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4289 optional_arg = (sym->attr.optional
4290 || (sym->ns->proc_name->attr.entry_master
4291 && sym->attr.dummy));
4292 if (optional_arg)
4294 tmp = gfc_conv_expr_present (sym);
4295 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4297 gfc_add_expr_to_block (&block, stmt);
4299 /* Add the main function body. */
4300 gfc_add_expr_to_block (&block, body);
4302 /* Cleanup code. */
4303 if (!no_repack)
4305 gfc_start_block (&cleanup);
4307 if (sym->attr.intent != INTENT_IN)
4309 /* Copy the data back. */
4310 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
4311 gfc_add_expr_to_block (&cleanup, tmp);
4314 /* Free the temporary. */
4315 tmp = gfc_call_free (tmpdesc);
4316 gfc_add_expr_to_block (&cleanup, tmp);
4318 stmt = gfc_finish_block (&cleanup);
4320 /* Only do the cleanup if the array was repacked. */
4321 tmp = build_fold_indirect_ref (dumdesc);
4322 tmp = gfc_conv_descriptor_data_get (tmp);
4323 tmp = build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
4324 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4326 if (optional_arg)
4328 tmp = gfc_conv_expr_present (sym);
4329 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4331 gfc_add_expr_to_block (&block, stmt);
4333 /* We don't need to free any memory allocated by internal_pack as it will
4334 be freed at the end of the function by pop_context. */
4335 return gfc_finish_block (&block);
4339 /* Convert an array for passing as an actual argument. Expressions and
4340 vector subscripts are evaluated and stored in a temporary, which is then
4341 passed. For whole arrays the descriptor is passed. For array sections
4342 a modified copy of the descriptor is passed, but using the original data.
4344 This function is also used for array pointer assignments, and there
4345 are three cases:
4347 - se->want_pointer && !se->direct_byref
4348 EXPR is an actual argument. On exit, se->expr contains a
4349 pointer to the array descriptor.
4351 - !se->want_pointer && !se->direct_byref
4352 EXPR is an actual argument to an intrinsic function or the
4353 left-hand side of a pointer assignment. On exit, se->expr
4354 contains the descriptor for EXPR.
4356 - !se->want_pointer && se->direct_byref
4357 EXPR is the right-hand side of a pointer assignment and
4358 se->expr is the descriptor for the previously-evaluated
4359 left-hand side. The function creates an assignment from
4360 EXPR to se->expr. */
4362 void
4363 gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
4365 gfc_loopinfo loop;
4366 gfc_ss *secss;
4367 gfc_ss_info *info;
4368 int need_tmp;
4369 int n;
4370 tree tmp;
4371 tree desc;
4372 stmtblock_t block;
4373 tree start;
4374 tree offset;
4375 int full;
4377 gcc_assert (ss != gfc_ss_terminator);
4379 /* Special case things we know we can pass easily. */
4380 switch (expr->expr_type)
4382 case EXPR_VARIABLE:
4383 /* If we have a linear array section, we can pass it directly.
4384 Otherwise we need to copy it into a temporary. */
4386 /* Find the SS for the array section. */
4387 secss = ss;
4388 while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
4389 secss = secss->next;
4391 gcc_assert (secss != gfc_ss_terminator);
4392 info = &secss->data.info;
4394 /* Get the descriptor for the array. */
4395 gfc_conv_ss_descriptor (&se->pre, secss, 0);
4396 desc = info->descriptor;
4398 need_tmp = gfc_ref_needs_temporary_p (expr->ref);
4399 if (need_tmp)
4400 full = 0;
4401 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4403 /* Create a new descriptor if the array doesn't have one. */
4404 full = 0;
4406 else if (info->ref->u.ar.type == AR_FULL)
4407 full = 1;
4408 else if (se->direct_byref)
4409 full = 0;
4410 else
4411 full = gfc_full_array_ref_p (info->ref);
4413 if (full)
4415 if (se->direct_byref)
4417 /* Copy the descriptor for pointer assignments. */
4418 gfc_add_modify_expr (&se->pre, se->expr, desc);
4420 else if (se->want_pointer)
4422 /* We pass full arrays directly. This means that pointers and
4423 allocatable arrays should also work. */
4424 se->expr = build_fold_addr_expr (desc);
4426 else
4428 se->expr = desc;
4431 if (expr->ts.type == BT_CHARACTER)
4432 se->string_length = gfc_get_expr_charlen (expr);
4434 return;
4436 break;
4438 case EXPR_FUNCTION:
4439 /* A transformational function return value will be a temporary
4440 array descriptor. We still need to go through the scalarizer
4441 to create the descriptor. Elemental functions ar handled as
4442 arbitrary expressions, i.e. copy to a temporary. */
4443 secss = ss;
4444 /* Look for the SS for this function. */
4445 while (secss != gfc_ss_terminator
4446 && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
4447 secss = secss->next;
4449 if (se->direct_byref)
4451 gcc_assert (secss != gfc_ss_terminator);
4453 /* For pointer assignments pass the descriptor directly. */
4454 se->ss = secss;
4455 se->expr = build_fold_addr_expr (se->expr);
4456 gfc_conv_expr (se, expr);
4457 return;
4460 if (secss == gfc_ss_terminator)
4462 /* Elemental function. */
4463 need_tmp = 1;
4464 info = NULL;
4466 else
4468 /* Transformational function. */
4469 info = &secss->data.info;
4470 need_tmp = 0;
4472 break;
4474 case EXPR_ARRAY:
4475 /* Constant array constructors don't need a temporary. */
4476 if (ss->type == GFC_SS_CONSTRUCTOR
4477 && expr->ts.type != BT_CHARACTER
4478 && gfc_constant_array_constructor_p (expr->value.constructor))
4480 need_tmp = 0;
4481 info = &ss->data.info;
4482 secss = ss;
4484 else
4486 need_tmp = 1;
4487 secss = NULL;
4488 info = NULL;
4490 break;
4492 default:
4493 /* Something complicated. Copy it into a temporary. */
4494 need_tmp = 1;
4495 secss = NULL;
4496 info = NULL;
4497 break;
4501 gfc_init_loopinfo (&loop);
4503 /* Associate the SS with the loop. */
4504 gfc_add_ss_to_loop (&loop, ss);
4506 /* Tell the scalarizer not to bother creating loop variables, etc. */
4507 if (!need_tmp)
4508 loop.array_parameter = 1;
4509 else
4510 /* The right-hand side of a pointer assignment mustn't use a temporary. */
4511 gcc_assert (!se->direct_byref);
4513 /* Setup the scalarizing loops and bounds. */
4514 gfc_conv_ss_startstride (&loop);
4516 if (need_tmp)
4518 /* Tell the scalarizer to make a temporary. */
4519 loop.temp_ss = gfc_get_ss ();
4520 loop.temp_ss->type = GFC_SS_TEMP;
4521 loop.temp_ss->next = gfc_ss_terminator;
4523 if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl)
4524 gfc_conv_string_length (expr->ts.cl, &se->pre);
4526 loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
4528 if (expr->ts.type == BT_CHARACTER)
4529 loop.temp_ss->string_length = expr->ts.cl->backend_decl;
4530 else
4531 loop.temp_ss->string_length = NULL;
4533 se->string_length = loop.temp_ss->string_length;
4534 loop.temp_ss->data.temp.dimen = loop.dimen;
4535 gfc_add_ss_to_loop (&loop, loop.temp_ss);
4538 gfc_conv_loop_setup (&loop);
4540 if (need_tmp)
4542 /* Copy into a temporary and pass that. We don't need to copy the data
4543 back because expressions and vector subscripts must be INTENT_IN. */
4544 /* TODO: Optimize passing function return values. */
4545 gfc_se lse;
4546 gfc_se rse;
4548 /* Start the copying loops. */
4549 gfc_mark_ss_chain_used (loop.temp_ss, 1);
4550 gfc_mark_ss_chain_used (ss, 1);
4551 gfc_start_scalarized_body (&loop, &block);
4553 /* Copy each data element. */
4554 gfc_init_se (&lse, NULL);
4555 gfc_copy_loopinfo_to_se (&lse, &loop);
4556 gfc_init_se (&rse, NULL);
4557 gfc_copy_loopinfo_to_se (&rse, &loop);
4559 lse.ss = loop.temp_ss;
4560 rse.ss = ss;
4562 gfc_conv_scalarized_array_ref (&lse, NULL);
4563 if (expr->ts.type == BT_CHARACTER)
4565 gfc_conv_expr (&rse, expr);
4566 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
4567 rse.expr = build_fold_indirect_ref (rse.expr);
4569 else
4570 gfc_conv_expr_val (&rse, expr);
4572 gfc_add_block_to_block (&block, &rse.pre);
4573 gfc_add_block_to_block (&block, &lse.pre);
4575 gfc_add_modify_expr (&block, lse.expr, rse.expr);
4577 /* Finish the copying loops. */
4578 gfc_trans_scalarizing_loops (&loop, &block);
4580 desc = loop.temp_ss->data.info.descriptor;
4582 gcc_assert (is_gimple_lvalue (desc));
4584 else if (expr->expr_type == EXPR_FUNCTION)
4586 desc = info->descriptor;
4587 se->string_length = ss->string_length;
4589 else
4591 /* We pass sections without copying to a temporary. Make a new
4592 descriptor and point it at the section we want. The loop variable
4593 limits will be the limits of the section.
4594 A function may decide to repack the array to speed up access, but
4595 we're not bothered about that here. */
4596 int dim, ndim;
4597 tree parm;
4598 tree parmtype;
4599 tree stride;
4600 tree from;
4601 tree to;
4602 tree base;
4604 /* Set the string_length for a character array. */
4605 if (expr->ts.type == BT_CHARACTER)
4606 se->string_length = gfc_get_expr_charlen (expr);
4608 desc = info->descriptor;
4609 gcc_assert (secss && secss != gfc_ss_terminator);
4610 if (se->direct_byref)
4612 /* For pointer assignments we fill in the destination. */
4613 parm = se->expr;
4614 parmtype = TREE_TYPE (parm);
4616 else
4618 /* Otherwise make a new one. */
4619 parmtype = gfc_get_element_type (TREE_TYPE (desc));
4620 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
4621 loop.from, loop.to, 0);
4622 parm = gfc_create_var (parmtype, "parm");
4625 offset = gfc_index_zero_node;
4626 dim = 0;
4628 /* The following can be somewhat confusing. We have two
4629 descriptors, a new one and the original array.
4630 {parm, parmtype, dim} refer to the new one.
4631 {desc, type, n, secss, loop} refer to the original, which maybe
4632 a descriptorless array.
4633 The bounds of the scalarization are the bounds of the section.
4634 We don't have to worry about numeric overflows when calculating
4635 the offsets because all elements are within the array data. */
4637 /* Set the dtype. */
4638 tmp = gfc_conv_descriptor_dtype (parm);
4639 gfc_add_modify_expr (&loop.pre, tmp, gfc_get_dtype (parmtype));
4641 /* Set offset for assignments to pointer only to zero if it is not
4642 the full array. */
4643 if (se->direct_byref
4644 && info->ref && info->ref->u.ar.type != AR_FULL)
4645 base = gfc_index_zero_node;
4646 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4647 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
4648 else
4649 base = NULL_TREE;
4651 ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
4652 for (n = 0; n < ndim; n++)
4654 stride = gfc_conv_array_stride (desc, n);
4656 /* Work out the offset. */
4657 if (info->ref
4658 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4660 gcc_assert (info->subscript[n]
4661 && info->subscript[n]->type == GFC_SS_SCALAR);
4662 start = info->subscript[n]->data.scalar.expr;
4664 else
4666 /* Check we haven't somehow got out of sync. */
4667 gcc_assert (info->dim[dim] == n);
4669 /* Evaluate and remember the start of the section. */
4670 start = info->start[dim];
4671 stride = gfc_evaluate_now (stride, &loop.pre);
4674 tmp = gfc_conv_array_lbound (desc, n);
4675 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp);
4677 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
4678 offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
4680 if (info->ref
4681 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4683 /* For elemental dimensions, we only need the offset. */
4684 continue;
4687 /* Vector subscripts need copying and are handled elsewhere. */
4688 if (info->ref)
4689 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
4691 /* Set the new lower bound. */
4692 from = loop.from[dim];
4693 to = loop.to[dim];
4695 /* If we have an array section or are assigning make sure that
4696 the lower bound is 1. References to the full
4697 array should otherwise keep the original bounds. */
4698 if ((!info->ref
4699 || info->ref->u.ar.type != AR_FULL)
4700 && !integer_onep (from))
4702 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4703 gfc_index_one_node, from);
4704 to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
4705 from = gfc_index_one_node;
4707 tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
4708 gfc_add_modify_expr (&loop.pre, tmp, from);
4710 /* Set the new upper bound. */
4711 tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
4712 gfc_add_modify_expr (&loop.pre, tmp, to);
4714 /* Multiply the stride by the section stride to get the
4715 total stride. */
4716 stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
4717 stride, info->stride[dim]);
4719 if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
4721 base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
4722 base, stride);
4724 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4726 tmp = gfc_conv_array_lbound (desc, n);
4727 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
4728 tmp, loop.from[dim]);
4729 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base),
4730 tmp, gfc_conv_array_stride (desc, n));
4731 base = fold_build2 (PLUS_EXPR, TREE_TYPE (base),
4732 tmp, base);
4735 /* Store the new stride. */
4736 tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
4737 gfc_add_modify_expr (&loop.pre, tmp, stride);
4739 dim++;
4742 if (se->data_not_needed)
4743 gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
4744 else
4746 /* Point the data pointer at the first element in the section. */
4747 tmp = gfc_conv_array_data (desc);
4748 tmp = build_fold_indirect_ref (tmp);
4749 tmp = gfc_build_array_ref (tmp, offset);
4750 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
4751 gfc_conv_descriptor_data_set (&loop.pre, parm, offset);
4754 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4755 && !se->data_not_needed)
4757 /* Set the offset. */
4758 tmp = gfc_conv_descriptor_offset (parm);
4759 gfc_add_modify_expr (&loop.pre, tmp, base);
4761 else
4763 /* Only the callee knows what the correct offset it, so just set
4764 it to zero here. */
4765 tmp = gfc_conv_descriptor_offset (parm);
4766 gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
4768 desc = parm;
4771 if (!se->direct_byref)
4773 /* Get a pointer to the new descriptor. */
4774 if (se->want_pointer)
4775 se->expr = build_fold_addr_expr (desc);
4776 else
4777 se->expr = desc;
4780 gfc_add_block_to_block (&se->pre, &loop.pre);
4781 gfc_add_block_to_block (&se->post, &loop.post);
4783 /* Cleanup the scalarizer. */
4784 gfc_cleanup_loop (&loop);
4788 /* Convert an array for passing as an actual parameter. */
4789 /* TODO: Optimize passing g77 arrays. */
4791 void
4792 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
4794 tree ptr;
4795 tree desc;
4796 tree tmp = NULL_TREE;
4797 tree stmt;
4798 tree parent = DECL_CONTEXT (current_function_decl);
4799 bool full_array_var, this_array_result;
4800 gfc_symbol *sym;
4801 stmtblock_t block;
4803 full_array_var = (expr->expr_type == EXPR_VARIABLE
4804 && expr->ref->u.ar.type == AR_FULL);
4805 sym = full_array_var ? expr->symtree->n.sym : NULL;
4807 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
4809 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
4810 expr->ts.cl->backend_decl = gfc_evaluate_now (tmp, &se->pre);
4811 se->string_length = expr->ts.cl->backend_decl;
4814 /* Is this the result of the enclosing procedure? */
4815 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
4816 if (this_array_result
4817 && (sym->backend_decl != current_function_decl)
4818 && (sym->backend_decl != parent))
4819 this_array_result = false;
4821 /* Passing address of the array if it is not pointer or assumed-shape. */
4822 if (full_array_var && g77 && !this_array_result)
4824 tmp = gfc_get_symbol_decl (sym);
4826 if (sym->ts.type == BT_CHARACTER)
4827 se->string_length = sym->ts.cl->backend_decl;
4828 if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE
4829 && !sym->attr.allocatable)
4831 /* Some variables are declared directly, others are declared as
4832 pointers and allocated on the heap. */
4833 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
4834 se->expr = tmp;
4835 else
4836 se->expr = build_fold_addr_expr (tmp);
4837 return;
4839 if (sym->attr.allocatable)
4841 if (sym->attr.dummy)
4843 gfc_conv_expr_descriptor (se, expr, ss);
4844 se->expr = gfc_conv_array_data (se->expr);
4846 else
4847 se->expr = gfc_conv_array_data (tmp);
4848 return;
4852 if (this_array_result)
4854 /* Result of the enclosing function. */
4855 gfc_conv_expr_descriptor (se, expr, ss);
4856 se->expr = build_fold_addr_expr (se->expr);
4858 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
4859 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
4860 se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
4862 return;
4864 else
4866 /* Every other type of array. */
4867 se->want_pointer = 1;
4868 gfc_conv_expr_descriptor (se, expr, ss);
4872 /* Deallocate the allocatable components of structures that are
4873 not variable. */
4874 if (expr->ts.type == BT_DERIVED
4875 && expr->ts.derived->attr.alloc_comp
4876 && expr->expr_type != EXPR_VARIABLE)
4878 tmp = build_fold_indirect_ref (se->expr);
4879 tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
4880 gfc_add_expr_to_block (&se->post, tmp);
4883 if (g77)
4885 desc = se->expr;
4886 /* Repack the array. */
4887 ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
4888 ptr = gfc_evaluate_now (ptr, &se->pre);
4889 se->expr = ptr;
4891 gfc_start_block (&block);
4893 /* Copy the data back. */
4894 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
4895 gfc_add_expr_to_block (&block, tmp);
4897 /* Free the temporary. */
4898 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
4899 gfc_add_expr_to_block (&block, tmp);
4901 stmt = gfc_finish_block (&block);
4903 gfc_init_block (&block);
4904 /* Only if it was repacked. This code needs to be executed before the
4905 loop cleanup code. */
4906 tmp = build_fold_indirect_ref (desc);
4907 tmp = gfc_conv_array_data (tmp);
4908 tmp = build2 (NE_EXPR, boolean_type_node,
4909 fold_convert (TREE_TYPE (tmp), ptr), tmp);
4910 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4912 gfc_add_expr_to_block (&block, tmp);
4913 gfc_add_block_to_block (&block, &se->post);
4915 gfc_init_block (&se->post);
4916 gfc_add_block_to_block (&se->post, &block);
4921 /* Generate code to deallocate an array, if it is allocated. */
4923 tree
4924 gfc_trans_dealloc_allocated (tree descriptor)
4926 tree tmp;
4927 tree var;
4928 stmtblock_t block;
4930 gfc_start_block (&block);
4932 var = gfc_conv_descriptor_data_get (descriptor);
4933 STRIP_NOPS (var);
4935 /* Call array_deallocate with an int * present in the second argument.
4936 Although it is ignored here, it's presence ensures that arrays that
4937 are already deallocated are ignored. */
4938 tmp = gfc_deallocate_with_status (var, NULL_TREE, true);
4939 gfc_add_expr_to_block (&block, tmp);
4941 /* Zero the data pointer. */
4942 tmp = build2 (MODIFY_EXPR, void_type_node,
4943 var, build_int_cst (TREE_TYPE (var), 0));
4944 gfc_add_expr_to_block (&block, tmp);
4946 return gfc_finish_block (&block);
4950 /* This helper function calculates the size in words of a full array. */
4952 static tree
4953 get_full_array_size (stmtblock_t *block, tree decl, int rank)
4955 tree idx;
4956 tree nelems;
4957 tree tmp;
4958 idx = gfc_rank_cst[rank - 1];
4959 nelems = gfc_conv_descriptor_ubound (decl, idx);
4960 tmp = gfc_conv_descriptor_lbound (decl, idx);
4961 tmp = build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
4962 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
4963 tmp, gfc_index_one_node);
4964 tmp = gfc_evaluate_now (tmp, block);
4966 nelems = gfc_conv_descriptor_stride (decl, idx);
4967 tmp = build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
4968 return gfc_evaluate_now (tmp, block);
4972 /* Allocate dest to the same size as src, and copy src -> dest. */
4974 tree
4975 gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
4977 tree tmp;
4978 tree size;
4979 tree nelems;
4980 tree null_cond;
4981 tree null_data;
4982 stmtblock_t block;
4984 /* If the source is null, set the destination to null. */
4985 gfc_init_block (&block);
4986 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
4987 null_data = gfc_finish_block (&block);
4989 gfc_init_block (&block);
4991 nelems = get_full_array_size (&block, src, rank);
4992 size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
4993 fold_convert (gfc_array_index_type,
4994 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
4996 /* Allocate memory to the destination. */
4997 tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
4998 size);
4999 gfc_conv_descriptor_data_set (&block, dest, tmp);
5001 /* We know the temporary and the value will be the same length,
5002 so can use memcpy. */
5003 tmp = built_in_decls[BUILT_IN_MEMCPY];
5004 tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
5005 gfc_conv_descriptor_data_get (src), size);
5006 gfc_add_expr_to_block (&block, tmp);
5007 tmp = gfc_finish_block (&block);
5009 /* Null the destination if the source is null; otherwise do
5010 the allocate and copy. */
5011 null_cond = gfc_conv_descriptor_data_get (src);
5012 null_cond = convert (pvoid_type_node, null_cond);
5013 null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
5014 null_pointer_node);
5015 return build3_v (COND_EXPR, null_cond, tmp, null_data);
5019 /* Recursively traverse an object of derived type, generating code to
5020 deallocate, nullify or copy allocatable components. This is the work horse
5021 function for the functions named in this enum. */
5023 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
5025 static tree
5026 structure_alloc_comps (gfc_symbol * der_type, tree decl,
5027 tree dest, int rank, int purpose)
5029 gfc_component *c;
5030 gfc_loopinfo loop;
5031 stmtblock_t fnblock;
5032 stmtblock_t loopbody;
5033 tree tmp;
5034 tree comp;
5035 tree dcmp;
5036 tree nelems;
5037 tree index;
5038 tree var;
5039 tree cdecl;
5040 tree ctype;
5041 tree vref, dref;
5042 tree null_cond = NULL_TREE;
5044 gfc_init_block (&fnblock);
5046 if (POINTER_TYPE_P (TREE_TYPE (decl)))
5047 decl = build_fold_indirect_ref (decl);
5049 /* If this an array of derived types with allocatable components
5050 build a loop and recursively call this function. */
5051 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
5052 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5054 tmp = gfc_conv_array_data (decl);
5055 var = build_fold_indirect_ref (tmp);
5057 /* Get the number of elements - 1 and set the counter. */
5058 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5060 /* Use the descriptor for an allocatable array. Since this
5061 is a full array reference, we only need the descriptor
5062 information from dimension = rank. */
5063 tmp = get_full_array_size (&fnblock, decl, rank);
5064 tmp = build2 (MINUS_EXPR, gfc_array_index_type,
5065 tmp, gfc_index_one_node);
5067 null_cond = gfc_conv_descriptor_data_get (decl);
5068 null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
5069 build_int_cst (TREE_TYPE (null_cond), 0));
5071 else
5073 /* Otherwise use the TYPE_DOMAIN information. */
5074 tmp = array_type_nelts (TREE_TYPE (decl));
5075 tmp = fold_convert (gfc_array_index_type, tmp);
5078 /* Remember that this is, in fact, the no. of elements - 1. */
5079 nelems = gfc_evaluate_now (tmp, &fnblock);
5080 index = gfc_create_var (gfc_array_index_type, "S");
5082 /* Build the body of the loop. */
5083 gfc_init_block (&loopbody);
5085 vref = gfc_build_array_ref (var, index);
5087 if (purpose == COPY_ALLOC_COMP)
5089 tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
5090 gfc_add_expr_to_block (&fnblock, tmp);
5092 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (dest));
5093 dref = gfc_build_array_ref (tmp, index);
5094 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
5096 else
5097 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
5099 gfc_add_expr_to_block (&loopbody, tmp);
5101 /* Build the loop and return. */
5102 gfc_init_loopinfo (&loop);
5103 loop.dimen = 1;
5104 loop.from[0] = gfc_index_zero_node;
5105 loop.loopvar[0] = index;
5106 loop.to[0] = nelems;
5107 gfc_trans_scalarizing_loops (&loop, &loopbody);
5108 gfc_add_block_to_block (&fnblock, &loop.pre);
5110 tmp = gfc_finish_block (&fnblock);
5111 if (null_cond != NULL_TREE)
5112 tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
5114 return tmp;
5117 /* Otherwise, act on the components or recursively call self to
5118 act on a chain of components. */
5119 for (c = der_type->components; c; c = c->next)
5121 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
5122 && c->ts.derived->attr.alloc_comp;
5123 cdecl = c->backend_decl;
5124 ctype = TREE_TYPE (cdecl);
5126 switch (purpose)
5128 case DEALLOCATE_ALLOC_COMP:
5129 /* Do not deallocate the components of ultimate pointer
5130 components. */
5131 if (cmp_has_alloc_comps && !c->pointer)
5133 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5134 rank = c->as ? c->as->rank : 0;
5135 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5136 rank, purpose);
5137 gfc_add_expr_to_block (&fnblock, tmp);
5140 if (c->allocatable)
5142 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5143 tmp = gfc_trans_dealloc_allocated (comp);
5144 gfc_add_expr_to_block (&fnblock, tmp);
5146 break;
5148 case NULLIFY_ALLOC_COMP:
5149 if (c->pointer)
5150 continue;
5151 else if (c->allocatable)
5153 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5154 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
5156 else if (cmp_has_alloc_comps)
5158 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5159 rank = c->as ? c->as->rank : 0;
5160 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5161 rank, purpose);
5162 gfc_add_expr_to_block (&fnblock, tmp);
5164 break;
5166 case COPY_ALLOC_COMP:
5167 if (c->pointer)
5168 continue;
5170 /* We need source and destination components. */
5171 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5172 dcmp = build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
5173 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
5175 if (c->allocatable && !cmp_has_alloc_comps)
5177 tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
5178 gfc_add_expr_to_block (&fnblock, tmp);
5181 if (cmp_has_alloc_comps)
5183 rank = c->as ? c->as->rank : 0;
5184 tmp = fold_convert (TREE_TYPE (dcmp), comp);
5185 gfc_add_modify_expr (&fnblock, dcmp, tmp);
5186 tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
5187 rank, purpose);
5188 gfc_add_expr_to_block (&fnblock, tmp);
5190 break;
5192 default:
5193 gcc_unreachable ();
5194 break;
5198 return gfc_finish_block (&fnblock);
5201 /* Recursively traverse an object of derived type, generating code to
5202 nullify allocatable components. */
5204 tree
5205 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5207 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5208 NULLIFY_ALLOC_COMP);
5212 /* Recursively traverse an object of derived type, generating code to
5213 deallocate allocatable components. */
5215 tree
5216 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5218 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5219 DEALLOCATE_ALLOC_COMP);
5223 /* Recursively traverse an object of derived type, generating code to
5224 copy its allocatable components. */
5226 tree
5227 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
5229 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
5233 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
5234 Do likewise, recursively if necessary, with the allocatable components of
5235 derived types. */
5237 tree
5238 gfc_trans_deferred_array (gfc_symbol * sym, tree body)
5240 tree type;
5241 tree tmp;
5242 tree descriptor;
5243 stmtblock_t fnblock;
5244 locus loc;
5245 int rank;
5246 bool sym_has_alloc_comp;
5248 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
5249 && sym->ts.derived->attr.alloc_comp;
5251 /* Make sure the frontend gets these right. */
5252 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
5253 fatal_error ("Possible frontend bug: Deferred array size without pointer, "
5254 "allocatable attribute or derived type without allocatable "
5255 "components.");
5257 gfc_init_block (&fnblock);
5259 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
5260 || TREE_CODE (sym->backend_decl) == PARM_DECL);
5262 if (sym->ts.type == BT_CHARACTER
5263 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
5265 gfc_conv_string_length (sym->ts.cl, &fnblock);
5266 gfc_trans_vla_type_sizes (sym, &fnblock);
5269 /* Dummy and use associated variables don't need anything special. */
5270 if (sym->attr.dummy || sym->attr.use_assoc)
5272 gfc_add_expr_to_block (&fnblock, body);
5274 return gfc_finish_block (&fnblock);
5277 gfc_get_backend_locus (&loc);
5278 gfc_set_backend_locus (&sym->declared_at);
5279 descriptor = sym->backend_decl;
5281 /* Although static, derived types with default initializers and
5282 allocatable components must not be nulled wholesale; instead they
5283 are treated component by component. */
5284 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
5286 /* SAVEd variables are not freed on exit. */
5287 gfc_trans_static_array_pointer (sym);
5288 return body;
5291 /* Get the descriptor type. */
5292 type = TREE_TYPE (sym->backend_decl);
5294 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
5296 if (!sym->attr.save)
5298 rank = sym->as ? sym->as->rank : 0;
5299 tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
5300 gfc_add_expr_to_block (&fnblock, tmp);
5303 else if (!GFC_DESCRIPTOR_TYPE_P (type))
5305 /* If the backend_decl is not a descriptor, we must have a pointer
5306 to one. */
5307 descriptor = build_fold_indirect_ref (sym->backend_decl);
5308 type = TREE_TYPE (descriptor);
5311 /* NULLIFY the data pointer. */
5312 if (GFC_DESCRIPTOR_TYPE_P (type))
5313 gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
5315 gfc_add_expr_to_block (&fnblock, body);
5317 gfc_set_backend_locus (&loc);
5319 /* Allocatable arrays need to be freed when they go out of scope.
5320 The allocatable components of pointers must not be touched. */
5321 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
5322 && !sym->attr.pointer && !sym->attr.save)
5324 int rank;
5325 rank = sym->as ? sym->as->rank : 0;
5326 tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
5327 gfc_add_expr_to_block (&fnblock, tmp);
5330 if (sym->attr.allocatable)
5332 tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
5333 gfc_add_expr_to_block (&fnblock, tmp);
5336 return gfc_finish_block (&fnblock);
5339 /************ Expression Walking Functions ******************/
5341 /* Walk a variable reference.
5343 Possible extension - multiple component subscripts.
5344 x(:,:) = foo%a(:)%b(:)
5345 Transforms to
5346 forall (i=..., j=...)
5347 x(i,j) = foo%a(j)%b(i)
5348 end forall
5349 This adds a fair amount of complexity because you need to deal with more
5350 than one ref. Maybe handle in a similar manner to vector subscripts.
5351 Maybe not worth the effort. */
5354 static gfc_ss *
5355 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
5357 gfc_ref *ref;
5358 gfc_array_ref *ar;
5359 gfc_ss *newss;
5360 gfc_ss *head;
5361 int n;
5363 for (ref = expr->ref; ref; ref = ref->next)
5364 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
5365 break;
5367 for (; ref; ref = ref->next)
5369 if (ref->type == REF_SUBSTRING)
5371 newss = gfc_get_ss ();
5372 newss->type = GFC_SS_SCALAR;
5373 newss->expr = ref->u.ss.start;
5374 newss->next = ss;
5375 ss = newss;
5377 newss = gfc_get_ss ();
5378 newss->type = GFC_SS_SCALAR;
5379 newss->expr = ref->u.ss.end;
5380 newss->next = ss;
5381 ss = newss;
5384 /* We're only interested in array sections from now on. */
5385 if (ref->type != REF_ARRAY)
5386 continue;
5388 ar = &ref->u.ar;
5389 switch (ar->type)
5391 case AR_ELEMENT:
5392 for (n = 0; n < ar->dimen; n++)
5394 newss = gfc_get_ss ();
5395 newss->type = GFC_SS_SCALAR;
5396 newss->expr = ar->start[n];
5397 newss->next = ss;
5398 ss = newss;
5400 break;
5402 case AR_FULL:
5403 newss = gfc_get_ss ();
5404 newss->type = GFC_SS_SECTION;
5405 newss->expr = expr;
5406 newss->next = ss;
5407 newss->data.info.dimen = ar->as->rank;
5408 newss->data.info.ref = ref;
5410 /* Make sure array is the same as array(:,:), this way
5411 we don't need to special case all the time. */
5412 ar->dimen = ar->as->rank;
5413 for (n = 0; n < ar->dimen; n++)
5415 newss->data.info.dim[n] = n;
5416 ar->dimen_type[n] = DIMEN_RANGE;
5418 gcc_assert (ar->start[n] == NULL);
5419 gcc_assert (ar->end[n] == NULL);
5420 gcc_assert (ar->stride[n] == NULL);
5422 ss = newss;
5423 break;
5425 case AR_SECTION:
5426 newss = gfc_get_ss ();
5427 newss->type = GFC_SS_SECTION;
5428 newss->expr = expr;
5429 newss->next = ss;
5430 newss->data.info.dimen = 0;
5431 newss->data.info.ref = ref;
5433 head = newss;
5435 /* We add SS chains for all the subscripts in the section. */
5436 for (n = 0; n < ar->dimen; n++)
5438 gfc_ss *indexss;
5440 switch (ar->dimen_type[n])
5442 case DIMEN_ELEMENT:
5443 /* Add SS for elemental (scalar) subscripts. */
5444 gcc_assert (ar->start[n]);
5445 indexss = gfc_get_ss ();
5446 indexss->type = GFC_SS_SCALAR;
5447 indexss->expr = ar->start[n];
5448 indexss->next = gfc_ss_terminator;
5449 indexss->loop_chain = gfc_ss_terminator;
5450 newss->data.info.subscript[n] = indexss;
5451 break;
5453 case DIMEN_RANGE:
5454 /* We don't add anything for sections, just remember this
5455 dimension for later. */
5456 newss->data.info.dim[newss->data.info.dimen] = n;
5457 newss->data.info.dimen++;
5458 break;
5460 case DIMEN_VECTOR:
5461 /* Create a GFC_SS_VECTOR index in which we can store
5462 the vector's descriptor. */
5463 indexss = gfc_get_ss ();
5464 indexss->type = GFC_SS_VECTOR;
5465 indexss->expr = ar->start[n];
5466 indexss->next = gfc_ss_terminator;
5467 indexss->loop_chain = gfc_ss_terminator;
5468 newss->data.info.subscript[n] = indexss;
5469 newss->data.info.dim[newss->data.info.dimen] = n;
5470 newss->data.info.dimen++;
5471 break;
5473 default:
5474 /* We should know what sort of section it is by now. */
5475 gcc_unreachable ();
5478 /* We should have at least one non-elemental dimension. */
5479 gcc_assert (newss->data.info.dimen > 0);
5480 ss = newss;
5481 break;
5483 default:
5484 /* We should know what sort of section it is by now. */
5485 gcc_unreachable ();
5489 return ss;
5493 /* Walk an expression operator. If only one operand of a binary expression is
5494 scalar, we must also add the scalar term to the SS chain. */
5496 static gfc_ss *
5497 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
5499 gfc_ss *head;
5500 gfc_ss *head2;
5501 gfc_ss *newss;
5503 head = gfc_walk_subexpr (ss, expr->value.op.op1);
5504 if (expr->value.op.op2 == NULL)
5505 head2 = head;
5506 else
5507 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
5509 /* All operands are scalar. Pass back and let the caller deal with it. */
5510 if (head2 == ss)
5511 return head2;
5513 /* All operands require scalarization. */
5514 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
5515 return head2;
5517 /* One of the operands needs scalarization, the other is scalar.
5518 Create a gfc_ss for the scalar expression. */
5519 newss = gfc_get_ss ();
5520 newss->type = GFC_SS_SCALAR;
5521 if (head == ss)
5523 /* First operand is scalar. We build the chain in reverse order, so
5524 add the scarar SS after the second operand. */
5525 head = head2;
5526 while (head && head->next != ss)
5527 head = head->next;
5528 /* Check we haven't somehow broken the chain. */
5529 gcc_assert (head);
5530 newss->next = ss;
5531 head->next = newss;
5532 newss->expr = expr->value.op.op1;
5534 else /* head2 == head */
5536 gcc_assert (head2 == head);
5537 /* Second operand is scalar. */
5538 newss->next = head2;
5539 head2 = newss;
5540 newss->expr = expr->value.op.op2;
5543 return head2;
5547 /* Reverse a SS chain. */
5549 gfc_ss *
5550 gfc_reverse_ss (gfc_ss * ss)
5552 gfc_ss *next;
5553 gfc_ss *head;
5555 gcc_assert (ss != NULL);
5557 head = gfc_ss_terminator;
5558 while (ss != gfc_ss_terminator)
5560 next = ss->next;
5561 /* Check we didn't somehow break the chain. */
5562 gcc_assert (next != NULL);
5563 ss->next = head;
5564 head = ss;
5565 ss = next;
5568 return (head);
5572 /* Walk the arguments of an elemental function. */
5574 gfc_ss *
5575 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
5576 gfc_ss_type type)
5578 int scalar;
5579 gfc_ss *head;
5580 gfc_ss *tail;
5581 gfc_ss *newss;
5583 head = gfc_ss_terminator;
5584 tail = NULL;
5585 scalar = 1;
5586 for (; arg; arg = arg->next)
5588 if (!arg->expr)
5589 continue;
5591 newss = gfc_walk_subexpr (head, arg->expr);
5592 if (newss == head)
5594 /* Scalar argument. */
5595 newss = gfc_get_ss ();
5596 newss->type = type;
5597 newss->expr = arg->expr;
5598 newss->next = head;
5600 else
5601 scalar = 0;
5603 head = newss;
5604 if (!tail)
5606 tail = head;
5607 while (tail->next != gfc_ss_terminator)
5608 tail = tail->next;
5612 if (scalar)
5614 /* If all the arguments are scalar we don't need the argument SS. */
5615 gfc_free_ss_chain (head);
5616 /* Pass it back. */
5617 return ss;
5620 /* Add it onto the existing chain. */
5621 tail->next = ss;
5622 return head;
5626 /* Walk a function call. Scalar functions are passed back, and taken out of
5627 scalarization loops. For elemental functions we walk their arguments.
5628 The result of functions returning arrays is stored in a temporary outside
5629 the loop, so that the function is only called once. Hence we do not need
5630 to walk their arguments. */
5632 static gfc_ss *
5633 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
5635 gfc_ss *newss;
5636 gfc_intrinsic_sym *isym;
5637 gfc_symbol *sym;
5639 isym = expr->value.function.isym;
5641 /* Handle intrinsic functions separately. */
5642 if (isym)
5643 return gfc_walk_intrinsic_function (ss, expr, isym);
5645 sym = expr->value.function.esym;
5646 if (!sym)
5647 sym = expr->symtree->n.sym;
5649 /* A function that returns arrays. */
5650 if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
5652 newss = gfc_get_ss ();
5653 newss->type = GFC_SS_FUNCTION;
5654 newss->expr = expr;
5655 newss->next = ss;
5656 newss->data.info.dimen = expr->rank;
5657 return newss;
5660 /* Walk the parameters of an elemental function. For now we always pass
5661 by reference. */
5662 if (sym->attr.elemental)
5663 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
5664 GFC_SS_REFERENCE);
5666 /* Scalar functions are OK as these are evaluated outside the scalarization
5667 loop. Pass back and let the caller deal with it. */
5668 return ss;
5672 /* An array temporary is constructed for array constructors. */
5674 static gfc_ss *
5675 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
5677 gfc_ss *newss;
5678 int n;
5680 newss = gfc_get_ss ();
5681 newss->type = GFC_SS_CONSTRUCTOR;
5682 newss->expr = expr;
5683 newss->next = ss;
5684 newss->data.info.dimen = expr->rank;
5685 for (n = 0; n < expr->rank; n++)
5686 newss->data.info.dim[n] = n;
5688 return newss;
5692 /* Walk an expression. Add walked expressions to the head of the SS chain.
5693 A wholly scalar expression will not be added. */
5695 static gfc_ss *
5696 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
5698 gfc_ss *head;
5700 switch (expr->expr_type)
5702 case EXPR_VARIABLE:
5703 head = gfc_walk_variable_expr (ss, expr);
5704 return head;
5706 case EXPR_OP:
5707 head = gfc_walk_op_expr (ss, expr);
5708 return head;
5710 case EXPR_FUNCTION:
5711 head = gfc_walk_function_expr (ss, expr);
5712 return head;
5714 case EXPR_CONSTANT:
5715 case EXPR_NULL:
5716 case EXPR_STRUCTURE:
5717 /* Pass back and let the caller deal with it. */
5718 break;
5720 case EXPR_ARRAY:
5721 head = gfc_walk_array_constructor (ss, expr);
5722 return head;
5724 case EXPR_SUBSTRING:
5725 /* Pass back and let the caller deal with it. */
5726 break;
5728 default:
5729 internal_error ("bad expression type during walk (%d)",
5730 expr->expr_type);
5732 return ss;
5736 /* Entry point for expression walking.
5737 A return value equal to the passed chain means this is
5738 a scalar expression. It is up to the caller to take whatever action is
5739 necessary to translate these. */
5741 gfc_ss *
5742 gfc_walk_expr (gfc_expr * expr)
5744 gfc_ss *res;
5746 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
5747 return gfc_reverse_ss (res);