install.texi (mips-*-*): Recommend binutils 2.18.
[official-gcc.git] / gcc / fortran / trans-array.c
blob41f01b848f271b99e8f6a54f0ade55e0921aae1c
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, NULL);
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 /* TODO: Investigate why "if (n < loop->temp_dim)
592 gcc_assert (integer_zerop (loop->from[n]));" fails here. */
593 if (n >= loop->temp_dim)
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 GFC_ARRAY_UNKNOWN);
613 desc = gfc_create_var (type, "atmp");
614 GFC_DECL_PACKED_ARRAY (desc) = 1;
616 info->descriptor = desc;
617 size = gfc_index_one_node;
619 /* Fill in the array dtype. */
620 tmp = gfc_conv_descriptor_dtype (desc);
621 gfc_add_modify_expr (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
624 Fill in the bounds and stride. This is a packed array, so:
626 size = 1;
627 for (n = 0; n < rank; n++)
629 stride[n] = size
630 delta = ubound[n] + 1 - lbound[n];
631 size = size * delta;
633 size = size * sizeof(element);
636 or_expr = NULL_TREE;
638 for (n = 0; n < info->dimen; n++)
640 if (loop->to[n] == NULL_TREE)
642 /* For a callee allocated array express the loop bounds in terms
643 of the descriptor fields. */
644 tmp = build2 (MINUS_EXPR, gfc_array_index_type,
645 gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
646 gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
647 loop->to[n] = tmp;
648 size = NULL_TREE;
649 continue;
652 /* Store the stride and bound components in the descriptor. */
653 tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
654 gfc_add_modify_expr (pre, tmp, size);
656 tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
657 gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
659 tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
660 gfc_add_modify_expr (pre, tmp, loop->to[n]);
662 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
663 loop->to[n], gfc_index_one_node);
665 /* Check whether the size for this dimension is negative. */
666 cond = fold_build2 (LE_EXPR, boolean_type_node, tmp,
667 gfc_index_zero_node);
668 cond = gfc_evaluate_now (cond, pre);
670 if (n == 0)
671 or_expr = cond;
672 else
673 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
675 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
676 size = gfc_evaluate_now (size, pre);
679 /* Get the size of the array. */
681 if (size && !callee_alloc)
683 /* If or_expr is true, then the extent in at least one
684 dimension is zero and the size is set to zero. */
685 size = fold_build3 (COND_EXPR, gfc_array_index_type,
686 or_expr, gfc_index_zero_node, size);
688 nelem = size;
689 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
690 fold_convert (gfc_array_index_type,
691 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
693 else
695 nelem = size;
696 size = NULL_TREE;
699 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, dynamic,
700 dealloc);
702 if (info->dimen > loop->temp_dim)
703 loop->temp_dim = info->dimen;
705 return size;
709 /* Generate code to transpose array EXPR by creating a new descriptor
710 in which the dimension specifications have been reversed. */
712 void
713 gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
715 tree dest, src, dest_index, src_index;
716 gfc_loopinfo *loop;
717 gfc_ss_info *dest_info, *src_info;
718 gfc_ss *dest_ss, *src_ss;
719 gfc_se src_se;
720 int n;
722 loop = se->loop;
724 src_ss = gfc_walk_expr (expr);
725 dest_ss = se->ss;
727 src_info = &src_ss->data.info;
728 dest_info = &dest_ss->data.info;
729 gcc_assert (dest_info->dimen == 2);
730 gcc_assert (src_info->dimen == 2);
732 /* Get a descriptor for EXPR. */
733 gfc_init_se (&src_se, NULL);
734 gfc_conv_expr_descriptor (&src_se, expr, src_ss);
735 gfc_add_block_to_block (&se->pre, &src_se.pre);
736 gfc_add_block_to_block (&se->post, &src_se.post);
737 src = src_se.expr;
739 /* Allocate a new descriptor for the return value. */
740 dest = gfc_create_var (TREE_TYPE (src), "atmp");
741 dest_info->descriptor = dest;
742 se->expr = dest;
744 /* Copy across the dtype field. */
745 gfc_add_modify_expr (&se->pre,
746 gfc_conv_descriptor_dtype (dest),
747 gfc_conv_descriptor_dtype (src));
749 /* Copy the dimension information, renumbering dimension 1 to 0 and
750 0 to 1. */
751 for (n = 0; n < 2; n++)
753 dest_info->delta[n] = gfc_index_zero_node;
754 dest_info->start[n] = gfc_index_zero_node;
755 dest_info->end[n] = gfc_index_zero_node;
756 dest_info->stride[n] = gfc_index_one_node;
757 dest_info->dim[n] = n;
759 dest_index = gfc_rank_cst[n];
760 src_index = gfc_rank_cst[1 - n];
762 gfc_add_modify_expr (&se->pre,
763 gfc_conv_descriptor_stride (dest, dest_index),
764 gfc_conv_descriptor_stride (src, src_index));
766 gfc_add_modify_expr (&se->pre,
767 gfc_conv_descriptor_lbound (dest, dest_index),
768 gfc_conv_descriptor_lbound (src, src_index));
770 gfc_add_modify_expr (&se->pre,
771 gfc_conv_descriptor_ubound (dest, dest_index),
772 gfc_conv_descriptor_ubound (src, src_index));
774 if (!loop->to[n])
776 gcc_assert (integer_zerop (loop->from[n]));
777 loop->to[n] = build2 (MINUS_EXPR, gfc_array_index_type,
778 gfc_conv_descriptor_ubound (dest, dest_index),
779 gfc_conv_descriptor_lbound (dest, dest_index));
783 /* Copy the data pointer. */
784 dest_info->data = gfc_conv_descriptor_data_get (src);
785 gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);
787 /* Copy the offset. This is not changed by transposition; the top-left
788 element is still at the same offset as before, except where the loop
789 starts at zero. */
790 if (!integer_zerop (loop->from[0]))
791 dest_info->offset = gfc_conv_descriptor_offset (src);
792 else
793 dest_info->offset = gfc_index_zero_node;
795 gfc_add_modify_expr (&se->pre,
796 gfc_conv_descriptor_offset (dest),
797 dest_info->offset);
799 if (dest_info->dimen > loop->temp_dim)
800 loop->temp_dim = dest_info->dimen;
804 /* Return the number of iterations in a loop that starts at START,
805 ends at END, and has step STEP. */
807 static tree
808 gfc_get_iteration_count (tree start, tree end, tree step)
810 tree tmp;
811 tree type;
813 type = TREE_TYPE (step);
814 tmp = fold_build2 (MINUS_EXPR, type, end, start);
815 tmp = fold_build2 (FLOOR_DIV_EXPR, type, tmp, step);
816 tmp = fold_build2 (PLUS_EXPR, type, tmp, build_int_cst (type, 1));
817 tmp = fold_build2 (MAX_EXPR, type, tmp, build_int_cst (type, 0));
818 return fold_convert (gfc_array_index_type, tmp);
822 /* Extend the data in array DESC by EXTRA elements. */
824 static void
825 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
827 tree arg0, arg1;
828 tree tmp;
829 tree size;
830 tree ubound;
832 if (integer_zerop (extra))
833 return;
835 ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
837 /* Add EXTRA to the upper bound. */
838 tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
839 gfc_add_modify_expr (pblock, ubound, tmp);
841 /* Get the value of the current data pointer. */
842 arg0 = gfc_conv_descriptor_data_get (desc);
844 /* Calculate the new array size. */
845 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
846 tmp = build2 (PLUS_EXPR, gfc_array_index_type, ubound, gfc_index_one_node);
847 arg1 = build2 (MULT_EXPR, size_type_node, fold_convert (size_type_node, tmp),
848 fold_convert (size_type_node, size));
850 /* Call the realloc() function. */
851 tmp = gfc_call_realloc (pblock, arg0, arg1);
852 gfc_conv_descriptor_data_set (pblock, desc, tmp);
856 /* Return true if the bounds of iterator I can only be determined
857 at run time. */
859 static inline bool
860 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
862 return (i->start->expr_type != EXPR_CONSTANT
863 || i->end->expr_type != EXPR_CONSTANT
864 || i->step->expr_type != EXPR_CONSTANT);
868 /* Split the size of constructor element EXPR into the sum of two terms,
869 one of which can be determined at compile time and one of which must
870 be calculated at run time. Set *SIZE to the former and return true
871 if the latter might be nonzero. */
873 static bool
874 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
876 if (expr->expr_type == EXPR_ARRAY)
877 return gfc_get_array_constructor_size (size, expr->value.constructor);
878 else if (expr->rank > 0)
880 /* Calculate everything at run time. */
881 mpz_set_ui (*size, 0);
882 return true;
884 else
886 /* A single element. */
887 mpz_set_ui (*size, 1);
888 return false;
893 /* Like gfc_get_array_constructor_element_size, but applied to the whole
894 of array constructor C. */
896 static bool
897 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
899 gfc_iterator *i;
900 mpz_t val;
901 mpz_t len;
902 bool dynamic;
904 mpz_set_ui (*size, 0);
905 mpz_init (len);
906 mpz_init (val);
908 dynamic = false;
909 for (; c; c = c->next)
911 i = c->iterator;
912 if (i && gfc_iterator_has_dynamic_bounds (i))
913 dynamic = true;
914 else
916 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
917 if (i)
919 /* Multiply the static part of the element size by the
920 number of iterations. */
921 mpz_sub (val, i->end->value.integer, i->start->value.integer);
922 mpz_fdiv_q (val, val, i->step->value.integer);
923 mpz_add_ui (val, val, 1);
924 if (mpz_sgn (val) > 0)
925 mpz_mul (len, len, val);
926 else
927 mpz_set_ui (len, 0);
929 mpz_add (*size, *size, len);
932 mpz_clear (len);
933 mpz_clear (val);
934 return dynamic;
938 /* Make sure offset is a variable. */
940 static void
941 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
942 tree * offsetvar)
944 /* We should have already created the offset variable. We cannot
945 create it here because we may be in an inner scope. */
946 gcc_assert (*offsetvar != NULL_TREE);
947 gfc_add_modify_expr (pblock, *offsetvar, *poffset);
948 *poffset = *offsetvar;
949 TREE_USED (*offsetvar) = 1;
953 /* Assign an element of an array constructor. */
954 static bool first_len;
955 static tree first_len_val;
957 static void
958 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
959 tree offset, gfc_se * se, gfc_expr * expr)
961 tree tmp;
962 tree esize;
964 gfc_conv_expr (se, expr);
966 /* Store the value. */
967 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
968 tmp = gfc_build_array_ref (tmp, offset, NULL);
970 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
971 esize = fold_convert (gfc_charlen_type_node, esize);
973 if (expr->ts.type == BT_CHARACTER)
975 gfc_conv_string_parameter (se);
976 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
978 /* The temporary is an array of pointers. */
979 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
980 gfc_add_modify_expr (&se->pre, tmp, se->expr);
982 else
984 /* The temporary is an array of string values. */
985 tmp = gfc_build_addr_expr (pchar_type_node, tmp);
986 /* We know the temporary and the value will be the same length,
987 so can use memcpy. */
988 gfc_trans_string_copy (&se->pre, esize, tmp,
989 se->string_length,
990 se->expr);
992 if (flag_bounds_check)
994 if (first_len)
996 gfc_add_modify_expr (&se->pre, first_len_val,
997 se->string_length);
998 first_len = false;
1000 else
1002 /* Verify that all constructor elements are of the same
1003 length. */
1004 tree cond = fold_build2 (NE_EXPR, boolean_type_node,
1005 first_len_val, se->string_length);
1006 gfc_trans_runtime_check
1007 (cond, &se->pre, &expr->where,
1008 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1009 fold_convert (long_integer_type_node, first_len_val),
1010 fold_convert (long_integer_type_node, se->string_length));
1014 else
1016 /* TODO: Should the frontend already have done this conversion? */
1017 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1018 gfc_add_modify_expr (&se->pre, tmp, se->expr);
1021 gfc_add_block_to_block (pblock, &se->pre);
1022 gfc_add_block_to_block (pblock, &se->post);
1026 /* Add the contents of an array to the constructor. DYNAMIC is as for
1027 gfc_trans_array_constructor_value. */
1029 static void
1030 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1031 tree type ATTRIBUTE_UNUSED,
1032 tree desc, gfc_expr * expr,
1033 tree * poffset, tree * offsetvar,
1034 bool dynamic)
1036 gfc_se se;
1037 gfc_ss *ss;
1038 gfc_loopinfo loop;
1039 stmtblock_t body;
1040 tree tmp;
1041 tree size;
1042 int n;
1044 /* We need this to be a variable so we can increment it. */
1045 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1047 gfc_init_se (&se, NULL);
1049 /* Walk the array expression. */
1050 ss = gfc_walk_expr (expr);
1051 gcc_assert (ss != gfc_ss_terminator);
1053 /* Initialize the scalarizer. */
1054 gfc_init_loopinfo (&loop);
1055 gfc_add_ss_to_loop (&loop, ss);
1057 /* Initialize the loop. */
1058 gfc_conv_ss_startstride (&loop);
1059 gfc_conv_loop_setup (&loop);
1061 /* Make sure the constructed array has room for the new data. */
1062 if (dynamic)
1064 /* Set SIZE to the total number of elements in the subarray. */
1065 size = gfc_index_one_node;
1066 for (n = 0; n < loop.dimen; n++)
1068 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1069 gfc_index_one_node);
1070 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1073 /* Grow the constructed array by SIZE elements. */
1074 gfc_grow_array (&loop.pre, desc, size);
1077 /* Make the loop body. */
1078 gfc_mark_ss_chain_used (ss, 1);
1079 gfc_start_scalarized_body (&loop, &body);
1080 gfc_copy_loopinfo_to_se (&se, &loop);
1081 se.ss = ss;
1083 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1084 gcc_assert (se.ss == gfc_ss_terminator);
1086 /* Increment the offset. */
1087 tmp = build2 (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node);
1088 gfc_add_modify_expr (&body, *poffset, tmp);
1090 /* Finish the loop. */
1091 gfc_trans_scalarizing_loops (&loop, &body);
1092 gfc_add_block_to_block (&loop.pre, &loop.post);
1093 tmp = gfc_finish_block (&loop.pre);
1094 gfc_add_expr_to_block (pblock, tmp);
1096 gfc_cleanup_loop (&loop);
1100 /* Assign the values to the elements of an array constructor. DYNAMIC
1101 is true if descriptor DESC only contains enough data for the static
1102 size calculated by gfc_get_array_constructor_size. When true, memory
1103 for the dynamic parts must be allocated using realloc. */
1105 static void
1106 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1107 tree desc, gfc_constructor * c,
1108 tree * poffset, tree * offsetvar,
1109 bool dynamic)
1111 tree tmp;
1112 stmtblock_t body;
1113 gfc_se se;
1114 mpz_t size;
1116 mpz_init (size);
1117 for (; c; c = c->next)
1119 /* If this is an iterator or an array, the offset must be a variable. */
1120 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1121 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1123 gfc_start_block (&body);
1125 if (c->expr->expr_type == EXPR_ARRAY)
1127 /* Array constructors can be nested. */
1128 gfc_trans_array_constructor_value (&body, type, desc,
1129 c->expr->value.constructor,
1130 poffset, offsetvar, dynamic);
1132 else if (c->expr->rank > 0)
1134 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1135 poffset, offsetvar, dynamic);
1137 else
1139 /* This code really upsets the gimplifier so don't bother for now. */
1140 gfc_constructor *p;
1141 HOST_WIDE_INT n;
1142 HOST_WIDE_INT size;
1144 p = c;
1145 n = 0;
1146 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1148 p = p->next;
1149 n++;
1151 if (n < 4)
1153 /* Scalar values. */
1154 gfc_init_se (&se, NULL);
1155 gfc_trans_array_ctor_element (&body, desc, *poffset,
1156 &se, c->expr);
1158 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1159 *poffset, gfc_index_one_node);
1161 else
1163 /* Collect multiple scalar constants into a constructor. */
1164 tree list;
1165 tree init;
1166 tree bound;
1167 tree tmptype;
1169 p = c;
1170 list = NULL_TREE;
1171 /* Count the number of consecutive scalar constants. */
1172 while (p && !(p->iterator
1173 || p->expr->expr_type != EXPR_CONSTANT))
1175 gfc_init_se (&se, NULL);
1176 gfc_conv_constant (&se, p->expr);
1177 if (p->expr->ts.type == BT_CHARACTER
1178 && POINTER_TYPE_P (type))
1180 /* For constant character array constructors we build
1181 an array of pointers. */
1182 se.expr = gfc_build_addr_expr (pchar_type_node,
1183 se.expr);
1186 list = tree_cons (NULL_TREE, se.expr, list);
1187 c = p;
1188 p = p->next;
1191 bound = build_int_cst (NULL_TREE, n - 1);
1192 /* Create an array type to hold them. */
1193 tmptype = build_range_type (gfc_array_index_type,
1194 gfc_index_zero_node, bound);
1195 tmptype = build_array_type (type, tmptype);
1197 init = build_constructor_from_list (tmptype, nreverse (list));
1198 TREE_CONSTANT (init) = 1;
1199 TREE_INVARIANT (init) = 1;
1200 TREE_STATIC (init) = 1;
1201 /* Create a static variable to hold the data. */
1202 tmp = gfc_create_var (tmptype, "data");
1203 TREE_STATIC (tmp) = 1;
1204 TREE_CONSTANT (tmp) = 1;
1205 TREE_INVARIANT (tmp) = 1;
1206 TREE_READONLY (tmp) = 1;
1207 DECL_INITIAL (tmp) = init;
1208 init = tmp;
1210 /* Use BUILTIN_MEMCPY to assign the values. */
1211 tmp = gfc_conv_descriptor_data_get (desc);
1212 tmp = build_fold_indirect_ref (tmp);
1213 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1214 tmp = build_fold_addr_expr (tmp);
1215 init = build_fold_addr_expr (init);
1217 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1218 bound = build_int_cst (NULL_TREE, n * size);
1219 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
1220 tmp, init, bound);
1221 gfc_add_expr_to_block (&body, tmp);
1223 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1224 *poffset,
1225 build_int_cst (gfc_array_index_type, n));
1227 if (!INTEGER_CST_P (*poffset))
1229 gfc_add_modify_expr (&body, *offsetvar, *poffset);
1230 *poffset = *offsetvar;
1234 /* The frontend should already have done any expansions possible
1235 at compile-time. */
1236 if (!c->iterator)
1238 /* Pass the code as is. */
1239 tmp = gfc_finish_block (&body);
1240 gfc_add_expr_to_block (pblock, tmp);
1242 else
1244 /* Build the implied do-loop. */
1245 tree cond;
1246 tree end;
1247 tree step;
1248 tree loopvar;
1249 tree exit_label;
1250 tree loopbody;
1251 tree tmp2;
1252 tree tmp_loopvar;
1254 loopbody = gfc_finish_block (&body);
1256 if (c->iterator->var->symtree->n.sym->backend_decl)
1258 gfc_init_se (&se, NULL);
1259 gfc_conv_expr (&se, c->iterator->var);
1260 gfc_add_block_to_block (pblock, &se.pre);
1261 loopvar = se.expr;
1263 else
1265 /* If the iterator appears in a specification expression in
1266 an interface mapping, we need to make a temp for the loop
1267 variable because it is not declared locally. */
1268 loopvar = gfc_typenode_for_spec (&c->iterator->var->ts);
1269 loopvar = gfc_create_var (loopvar, "loopvar");
1272 /* Make a temporary, store the current value in that
1273 and return it, once the loop is done. */
1274 tmp_loopvar = gfc_create_var (TREE_TYPE (loopvar), "loopvar");
1275 gfc_add_modify_expr (pblock, tmp_loopvar, loopvar);
1277 /* Initialize the loop. */
1278 gfc_init_se (&se, NULL);
1279 gfc_conv_expr_val (&se, c->iterator->start);
1280 gfc_add_block_to_block (pblock, &se.pre);
1281 gfc_add_modify_expr (pblock, loopvar, se.expr);
1283 gfc_init_se (&se, NULL);
1284 gfc_conv_expr_val (&se, c->iterator->end);
1285 gfc_add_block_to_block (pblock, &se.pre);
1286 end = gfc_evaluate_now (se.expr, pblock);
1288 gfc_init_se (&se, NULL);
1289 gfc_conv_expr_val (&se, c->iterator->step);
1290 gfc_add_block_to_block (pblock, &se.pre);
1291 step = gfc_evaluate_now (se.expr, pblock);
1293 /* If this array expands dynamically, and the number of iterations
1294 is not constant, we won't have allocated space for the static
1295 part of C->EXPR's size. Do that now. */
1296 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1298 /* Get the number of iterations. */
1299 tmp = gfc_get_iteration_count (loopvar, end, step);
1301 /* Get the static part of C->EXPR's size. */
1302 gfc_get_array_constructor_element_size (&size, c->expr);
1303 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1305 /* Grow the array by TMP * TMP2 elements. */
1306 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
1307 gfc_grow_array (pblock, desc, tmp);
1310 /* Generate the loop body. */
1311 exit_label = gfc_build_label_decl (NULL_TREE);
1312 gfc_start_block (&body);
1314 /* Generate the exit condition. Depending on the sign of
1315 the step variable we have to generate the correct
1316 comparison. */
1317 tmp = fold_build2 (GT_EXPR, boolean_type_node, step,
1318 build_int_cst (TREE_TYPE (step), 0));
1319 cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
1320 build2 (GT_EXPR, boolean_type_node,
1321 loopvar, end),
1322 build2 (LT_EXPR, boolean_type_node,
1323 loopvar, end));
1324 tmp = build1_v (GOTO_EXPR, exit_label);
1325 TREE_USED (exit_label) = 1;
1326 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1327 gfc_add_expr_to_block (&body, tmp);
1329 /* The main loop body. */
1330 gfc_add_expr_to_block (&body, loopbody);
1332 /* Increase loop variable by step. */
1333 tmp = build2 (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
1334 gfc_add_modify_expr (&body, loopvar, tmp);
1336 /* Finish the loop. */
1337 tmp = gfc_finish_block (&body);
1338 tmp = build1_v (LOOP_EXPR, tmp);
1339 gfc_add_expr_to_block (pblock, tmp);
1341 /* Add the exit label. */
1342 tmp = build1_v (LABEL_EXPR, exit_label);
1343 gfc_add_expr_to_block (pblock, tmp);
1345 /* Restore the original value of the loop counter. */
1346 gfc_add_modify_expr (pblock, loopvar, tmp_loopvar);
1349 mpz_clear (size);
1353 /* Figure out the string length of a variable reference expression.
1354 Used by get_array_ctor_strlen. */
1356 static void
1357 get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1359 gfc_ref *ref;
1360 gfc_typespec *ts;
1361 mpz_t char_len;
1363 /* Don't bother if we already know the length is a constant. */
1364 if (*len && INTEGER_CST_P (*len))
1365 return;
1367 ts = &expr->symtree->n.sym->ts;
1368 for (ref = expr->ref; ref; ref = ref->next)
1370 switch (ref->type)
1372 case REF_ARRAY:
1373 /* Array references don't change the string length. */
1374 break;
1376 case REF_COMPONENT:
1377 /* Use the length of the component. */
1378 ts = &ref->u.c.component->ts;
1379 break;
1381 case REF_SUBSTRING:
1382 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1383 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1384 break;
1385 mpz_init_set_ui (char_len, 1);
1386 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1387 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1388 *len = gfc_conv_mpz_to_tree (char_len,
1389 gfc_default_character_kind);
1390 *len = convert (gfc_charlen_type_node, *len);
1391 mpz_clear (char_len);
1392 return;
1394 default:
1395 /* TODO: Substrings are tricky because we can't evaluate the
1396 expression more than once. For now we just give up, and hope
1397 we can figure it out elsewhere. */
1398 return;
1402 *len = ts->cl->backend_decl;
1406 /* A catch-all to obtain the string length for anything that is not a
1407 constant, array or variable. */
1408 static void
1409 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1411 gfc_se se;
1412 gfc_ss *ss;
1414 /* Don't bother if we already know the length is a constant. */
1415 if (*len && INTEGER_CST_P (*len))
1416 return;
1418 if (!e->ref && e->ts.cl && e->ts.cl->length
1419 && e->ts.cl->length->expr_type == EXPR_CONSTANT)
1421 /* This is easy. */
1422 gfc_conv_const_charlen (e->ts.cl);
1423 *len = e->ts.cl->backend_decl;
1425 else
1427 /* Otherwise, be brutal even if inefficient. */
1428 ss = gfc_walk_expr (e);
1429 gfc_init_se (&se, NULL);
1431 /* No function call, in case of side effects. */
1432 se.no_function_call = 1;
1433 if (ss == gfc_ss_terminator)
1434 gfc_conv_expr (&se, e);
1435 else
1436 gfc_conv_expr_descriptor (&se, e, ss);
1438 /* Fix the value. */
1439 *len = gfc_evaluate_now (se.string_length, &se.pre);
1441 gfc_add_block_to_block (block, &se.pre);
1442 gfc_add_block_to_block (block, &se.post);
1444 e->ts.cl->backend_decl = *len;
1449 /* Figure out the string length of a character array constructor.
1450 Returns TRUE if all elements are character constants. */
1452 bool
1453 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
1455 bool is_const;
1457 is_const = TRUE;
1459 if (c == NULL)
1461 *len = build_int_cstu (gfc_charlen_type_node, 0);
1462 return is_const;
1465 for (; c; c = c->next)
1467 switch (c->expr->expr_type)
1469 case EXPR_CONSTANT:
1470 if (!(*len && INTEGER_CST_P (*len)))
1471 *len = build_int_cstu (gfc_charlen_type_node,
1472 c->expr->value.character.length);
1473 break;
1475 case EXPR_ARRAY:
1476 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1477 is_const = false;
1478 break;
1480 case EXPR_VARIABLE:
1481 is_const = false;
1482 get_array_ctor_var_strlen (c->expr, len);
1483 break;
1485 default:
1486 is_const = false;
1487 get_array_ctor_all_strlen (block, c->expr, len);
1488 break;
1492 return is_const;
1495 /* Check whether the array constructor C consists entirely of constant
1496 elements, and if so returns the number of those elements, otherwise
1497 return zero. Note, an empty or NULL array constructor returns zero. */
1499 unsigned HOST_WIDE_INT
1500 gfc_constant_array_constructor_p (gfc_constructor * c)
1502 unsigned HOST_WIDE_INT nelem = 0;
1504 while (c)
1506 if (c->iterator
1507 || c->expr->rank > 0
1508 || c->expr->expr_type != EXPR_CONSTANT)
1509 return 0;
1510 c = c->next;
1511 nelem++;
1513 return nelem;
1517 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1518 and the tree type of it's elements, TYPE, return a static constant
1519 variable that is compile-time initialized. */
1521 tree
1522 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1524 tree tmptype, list, init, tmp;
1525 HOST_WIDE_INT nelem;
1526 gfc_constructor *c;
1527 gfc_array_spec as;
1528 gfc_se se;
1529 int i;
1531 /* First traverse the constructor list, converting the constants
1532 to tree to build an initializer. */
1533 nelem = 0;
1534 list = NULL_TREE;
1535 c = expr->value.constructor;
1536 while (c)
1538 gfc_init_se (&se, NULL);
1539 gfc_conv_constant (&se, c->expr);
1540 if (c->expr->ts.type == BT_CHARACTER
1541 && POINTER_TYPE_P (type))
1542 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
1543 list = tree_cons (NULL_TREE, se.expr, list);
1544 c = c->next;
1545 nelem++;
1548 /* Next determine the tree type for the array. We use the gfortran
1549 front-end's gfc_get_nodesc_array_type in order to create a suitable
1550 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1552 memset (&as, 0, sizeof (gfc_array_spec));
1554 as.rank = expr->rank;
1555 as.type = AS_EXPLICIT;
1556 if (!expr->shape)
1558 as.lower[0] = gfc_int_expr (0);
1559 as.upper[0] = gfc_int_expr (nelem - 1);
1561 else
1562 for (i = 0; i < expr->rank; i++)
1564 int tmp = (int) mpz_get_si (expr->shape[i]);
1565 as.lower[i] = gfc_int_expr (0);
1566 as.upper[i] = gfc_int_expr (tmp - 1);
1569 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
1571 init = build_constructor_from_list (tmptype, nreverse (list));
1573 TREE_CONSTANT (init) = 1;
1574 TREE_INVARIANT (init) = 1;
1575 TREE_STATIC (init) = 1;
1577 tmp = gfc_create_var (tmptype, "A");
1578 TREE_STATIC (tmp) = 1;
1579 TREE_CONSTANT (tmp) = 1;
1580 TREE_INVARIANT (tmp) = 1;
1581 TREE_READONLY (tmp) = 1;
1582 DECL_INITIAL (tmp) = init;
1584 return tmp;
1588 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1589 This mostly initializes the scalarizer state info structure with the
1590 appropriate values to directly use the array created by the function
1591 gfc_build_constant_array_constructor. */
1593 static void
1594 gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
1595 gfc_ss * ss, tree type)
1597 gfc_ss_info *info;
1598 tree tmp;
1599 int i;
1601 tmp = gfc_build_constant_array_constructor (ss->expr, type);
1603 info = &ss->data.info;
1605 info->descriptor = tmp;
1606 info->data = build_fold_addr_expr (tmp);
1607 info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type,
1608 loop->from[0]);
1610 for (i = 0; i < info->dimen; i++)
1612 info->delta[i] = gfc_index_zero_node;
1613 info->start[i] = gfc_index_zero_node;
1614 info->end[i] = gfc_index_zero_node;
1615 info->stride[i] = gfc_index_one_node;
1616 info->dim[i] = i;
1619 if (info->dimen > loop->temp_dim)
1620 loop->temp_dim = info->dimen;
1623 /* Helper routine of gfc_trans_array_constructor to determine if the
1624 bounds of the loop specified by LOOP are constant and simple enough
1625 to use with gfc_trans_constant_array_constructor. Returns the
1626 the iteration count of the loop if suitable, and NULL_TREE otherwise. */
1628 static tree
1629 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1631 tree size = gfc_index_one_node;
1632 tree tmp;
1633 int i;
1635 for (i = 0; i < loop->dimen; i++)
1637 /* If the bounds aren't constant, return NULL_TREE. */
1638 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1639 return NULL_TREE;
1640 if (!integer_zerop (loop->from[i]))
1642 /* Only allow nonzero "from" in one-dimensional arrays. */
1643 if (loop->dimen != 1)
1644 return NULL_TREE;
1645 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1646 loop->to[i], loop->from[i]);
1648 else
1649 tmp = loop->to[i];
1650 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1651 tmp, gfc_index_one_node);
1652 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1655 return size;
1659 /* Array constructors are handled by constructing a temporary, then using that
1660 within the scalarization loop. This is not optimal, but seems by far the
1661 simplest method. */
1663 static void
1664 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
1666 gfc_constructor *c;
1667 tree offset;
1668 tree offsetvar;
1669 tree desc;
1670 tree type;
1671 bool dynamic;
1673 if (flag_bounds_check && ss->expr->ts.type == BT_CHARACTER)
1675 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1676 first_len = true;
1679 ss->data.info.dimen = loop->dimen;
1681 c = ss->expr->value.constructor;
1682 if (ss->expr->ts.type == BT_CHARACTER)
1684 bool const_string = get_array_ctor_strlen (&loop->pre, c, &ss->string_length);
1686 /* Complex character array constructors should have been taken care of
1687 and not end up here. */
1688 gcc_assert (ss->string_length);
1690 ss->expr->ts.cl->backend_decl = ss->string_length;
1692 type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1693 if (const_string)
1694 type = build_pointer_type (type);
1696 else
1697 type = gfc_typenode_for_spec (&ss->expr->ts);
1699 /* See if the constructor determines the loop bounds. */
1700 dynamic = false;
1702 if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
1704 /* We have a multidimensional parameter. */
1705 int n;
1706 for (n = 0; n < ss->expr->rank; n++)
1708 loop->from[n] = gfc_index_zero_node;
1709 loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
1710 gfc_index_integer_kind);
1711 loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1712 loop->to[n], gfc_index_one_node);
1716 if (loop->to[0] == NULL_TREE)
1718 mpz_t size;
1720 /* We should have a 1-dimensional, zero-based loop. */
1721 gcc_assert (loop->dimen == 1);
1722 gcc_assert (integer_zerop (loop->from[0]));
1724 /* Split the constructor size into a static part and a dynamic part.
1725 Allocate the static size up-front and record whether the dynamic
1726 size might be nonzero. */
1727 mpz_init (size);
1728 dynamic = gfc_get_array_constructor_size (&size, c);
1729 mpz_sub_ui (size, size, 1);
1730 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1731 mpz_clear (size);
1734 /* Special case constant array constructors. */
1735 if (!dynamic)
1737 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
1738 if (nelem > 0)
1740 tree size = constant_array_constructor_loop_size (loop);
1741 if (size && compare_tree_int (size, nelem) == 0)
1743 gfc_trans_constant_array_constructor (loop, ss, type);
1744 return;
1749 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
1750 type, dynamic, true, false);
1752 desc = ss->data.info.descriptor;
1753 offset = gfc_index_zero_node;
1754 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1755 TREE_NO_WARNING (offsetvar) = 1;
1756 TREE_USED (offsetvar) = 0;
1757 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
1758 &offset, &offsetvar, dynamic);
1760 /* If the array grows dynamically, the upper bound of the loop variable
1761 is determined by the array's final upper bound. */
1762 if (dynamic)
1763 loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
1765 if (TREE_USED (offsetvar))
1766 pushdecl (offsetvar);
1767 else
1768 gcc_assert (INTEGER_CST_P (offset));
1769 #if 0
1770 /* Disable bound checking for now because it's probably broken. */
1771 if (flag_bounds_check)
1773 gcc_unreachable ();
1775 #endif
1779 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
1780 called after evaluating all of INFO's vector dimensions. Go through
1781 each such vector dimension and see if we can now fill in any missing
1782 loop bounds. */
1784 static void
1785 gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
1787 gfc_se se;
1788 tree tmp;
1789 tree desc;
1790 tree zero;
1791 int n;
1792 int dim;
1794 for (n = 0; n < loop->dimen; n++)
1796 dim = info->dim[n];
1797 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
1798 && loop->to[n] == NULL)
1800 /* Loop variable N indexes vector dimension DIM, and we don't
1801 yet know the upper bound of loop variable N. Set it to the
1802 difference between the vector's upper and lower bounds. */
1803 gcc_assert (loop->from[n] == gfc_index_zero_node);
1804 gcc_assert (info->subscript[dim]
1805 && info->subscript[dim]->type == GFC_SS_VECTOR);
1807 gfc_init_se (&se, NULL);
1808 desc = info->subscript[dim]->data.info.descriptor;
1809 zero = gfc_rank_cst[0];
1810 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1811 gfc_conv_descriptor_ubound (desc, zero),
1812 gfc_conv_descriptor_lbound (desc, zero));
1813 tmp = gfc_evaluate_now (tmp, &loop->pre);
1814 loop->to[n] = tmp;
1820 /* Add the pre and post chains for all the scalar expressions in a SS chain
1821 to loop. This is called after the loop parameters have been calculated,
1822 but before the actual scalarizing loops. */
1824 static void
1825 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript)
1827 gfc_se se;
1828 int n;
1830 /* TODO: This can generate bad code if there are ordering dependencies.
1831 eg. a callee allocated function and an unknown size constructor. */
1832 gcc_assert (ss != NULL);
1834 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
1836 gcc_assert (ss);
1838 switch (ss->type)
1840 case GFC_SS_SCALAR:
1841 /* Scalar expression. Evaluate this now. This includes elemental
1842 dimension indices, but not array section bounds. */
1843 gfc_init_se (&se, NULL);
1844 gfc_conv_expr (&se, ss->expr);
1845 gfc_add_block_to_block (&loop->pre, &se.pre);
1847 if (ss->expr->ts.type != BT_CHARACTER)
1849 /* Move the evaluation of scalar expressions outside the
1850 scalarization loop. */
1851 if (subscript)
1852 se.expr = convert(gfc_array_index_type, se.expr);
1853 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
1854 gfc_add_block_to_block (&loop->pre, &se.post);
1856 else
1857 gfc_add_block_to_block (&loop->post, &se.post);
1859 ss->data.scalar.expr = se.expr;
1860 ss->string_length = se.string_length;
1861 break;
1863 case GFC_SS_REFERENCE:
1864 /* Scalar reference. Evaluate this now. */
1865 gfc_init_se (&se, NULL);
1866 gfc_conv_expr_reference (&se, ss->expr);
1867 gfc_add_block_to_block (&loop->pre, &se.pre);
1868 gfc_add_block_to_block (&loop->post, &se.post);
1870 ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
1871 ss->string_length = se.string_length;
1872 break;
1874 case GFC_SS_SECTION:
1875 /* Add the expressions for scalar and vector subscripts. */
1876 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1877 if (ss->data.info.subscript[n])
1878 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true);
1880 gfc_set_vector_loop_bounds (loop, &ss->data.info);
1881 break;
1883 case GFC_SS_VECTOR:
1884 /* Get the vector's descriptor and store it in SS. */
1885 gfc_init_se (&se, NULL);
1886 gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
1887 gfc_add_block_to_block (&loop->pre, &se.pre);
1888 gfc_add_block_to_block (&loop->post, &se.post);
1889 ss->data.info.descriptor = se.expr;
1890 break;
1892 case GFC_SS_INTRINSIC:
1893 gfc_add_intrinsic_ss_code (loop, ss);
1894 break;
1896 case GFC_SS_FUNCTION:
1897 /* Array function return value. We call the function and save its
1898 result in a temporary for use inside the loop. */
1899 gfc_init_se (&se, NULL);
1900 se.loop = loop;
1901 se.ss = ss;
1902 gfc_conv_expr (&se, ss->expr);
1903 gfc_add_block_to_block (&loop->pre, &se.pre);
1904 gfc_add_block_to_block (&loop->post, &se.post);
1905 ss->string_length = se.string_length;
1906 break;
1908 case GFC_SS_CONSTRUCTOR:
1909 if (ss->expr->ts.type == BT_CHARACTER
1910 && ss->string_length == NULL
1911 && ss->expr->ts.cl
1912 && ss->expr->ts.cl->length)
1914 gfc_init_se (&se, NULL);
1915 gfc_conv_expr_type (&se, ss->expr->ts.cl->length,
1916 gfc_charlen_type_node);
1917 ss->string_length = se.expr;
1918 gfc_add_block_to_block (&loop->pre, &se.pre);
1919 gfc_add_block_to_block (&loop->post, &se.post);
1921 gfc_trans_array_constructor (loop, ss);
1922 break;
1924 case GFC_SS_TEMP:
1925 case GFC_SS_COMPONENT:
1926 /* Do nothing. These are handled elsewhere. */
1927 break;
1929 default:
1930 gcc_unreachable ();
1936 /* Translate expressions for the descriptor and data pointer of a SS. */
1937 /*GCC ARRAYS*/
1939 static void
1940 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
1942 gfc_se se;
1943 tree tmp;
1945 /* Get the descriptor for the array to be scalarized. */
1946 gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
1947 gfc_init_se (&se, NULL);
1948 se.descriptor_only = 1;
1949 gfc_conv_expr_lhs (&se, ss->expr);
1950 gfc_add_block_to_block (block, &se.pre);
1951 ss->data.info.descriptor = se.expr;
1952 ss->string_length = se.string_length;
1954 if (base)
1956 /* Also the data pointer. */
1957 tmp = gfc_conv_array_data (se.expr);
1958 /* If this is a variable or address of a variable we use it directly.
1959 Otherwise we must evaluate it now to avoid breaking dependency
1960 analysis by pulling the expressions for elemental array indices
1961 inside the loop. */
1962 if (!(DECL_P (tmp)
1963 || (TREE_CODE (tmp) == ADDR_EXPR
1964 && DECL_P (TREE_OPERAND (tmp, 0)))))
1965 tmp = gfc_evaluate_now (tmp, block);
1966 ss->data.info.data = tmp;
1968 tmp = gfc_conv_array_offset (se.expr);
1969 ss->data.info.offset = gfc_evaluate_now (tmp, block);
1974 /* Initialize a gfc_loopinfo structure. */
1976 void
1977 gfc_init_loopinfo (gfc_loopinfo * loop)
1979 int n;
1981 memset (loop, 0, sizeof (gfc_loopinfo));
1982 gfc_init_block (&loop->pre);
1983 gfc_init_block (&loop->post);
1985 /* Initially scalarize in order. */
1986 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1987 loop->order[n] = n;
1989 loop->ss = gfc_ss_terminator;
1993 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
1994 chain. */
1996 void
1997 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
1999 se->loop = loop;
2003 /* Return an expression for the data pointer of an array. */
2005 tree
2006 gfc_conv_array_data (tree descriptor)
2008 tree type;
2010 type = TREE_TYPE (descriptor);
2011 if (GFC_ARRAY_TYPE_P (type))
2013 if (TREE_CODE (type) == POINTER_TYPE)
2014 return descriptor;
2015 else
2017 /* Descriptorless arrays. */
2018 return build_fold_addr_expr (descriptor);
2021 else
2022 return gfc_conv_descriptor_data_get (descriptor);
2026 /* Return an expression for the base offset of an array. */
2028 tree
2029 gfc_conv_array_offset (tree descriptor)
2031 tree type;
2033 type = TREE_TYPE (descriptor);
2034 if (GFC_ARRAY_TYPE_P (type))
2035 return GFC_TYPE_ARRAY_OFFSET (type);
2036 else
2037 return gfc_conv_descriptor_offset (descriptor);
2041 /* Get an expression for the array stride. */
2043 tree
2044 gfc_conv_array_stride (tree descriptor, int dim)
2046 tree tmp;
2047 tree type;
2049 type = TREE_TYPE (descriptor);
2051 /* For descriptorless arrays use the array size. */
2052 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2053 if (tmp != NULL_TREE)
2054 return tmp;
2056 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
2057 return tmp;
2061 /* Like gfc_conv_array_stride, but for the lower bound. */
2063 tree
2064 gfc_conv_array_lbound (tree descriptor, int dim)
2066 tree tmp;
2067 tree type;
2069 type = TREE_TYPE (descriptor);
2071 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2072 if (tmp != NULL_TREE)
2073 return tmp;
2075 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
2076 return tmp;
2080 /* Like gfc_conv_array_stride, but for the upper bound. */
2082 tree
2083 gfc_conv_array_ubound (tree descriptor, int dim)
2085 tree tmp;
2086 tree type;
2088 type = TREE_TYPE (descriptor);
2090 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2091 if (tmp != NULL_TREE)
2092 return tmp;
2094 /* This should only ever happen when passing an assumed shape array
2095 as an actual parameter. The value will never be used. */
2096 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2097 return gfc_index_zero_node;
2099 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
2100 return tmp;
2104 /* Generate code to perform an array index bound check. */
2106 static tree
2107 gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
2108 locus * where, bool check_upper)
2110 tree fault;
2111 tree tmp;
2112 char *msg;
2113 const char * name = NULL;
2115 if (!flag_bounds_check)
2116 return index;
2118 index = gfc_evaluate_now (index, &se->pre);
2120 /* We find a name for the error message. */
2121 if (se->ss)
2122 name = se->ss->expr->symtree->name;
2124 if (!name && se->loop && se->loop->ss && se->loop->ss->expr
2125 && se->loop->ss->expr->symtree)
2126 name = se->loop->ss->expr->symtree->name;
2128 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2129 && se->loop->ss->loop_chain->expr
2130 && se->loop->ss->loop_chain->expr->symtree)
2131 name = se->loop->ss->loop_chain->expr->symtree->name;
2133 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2134 && se->loop->ss->loop_chain->expr->symtree)
2135 name = se->loop->ss->loop_chain->expr->symtree->name;
2137 if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
2139 if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
2140 && se->loop->ss->expr->value.function.name)
2141 name = se->loop->ss->expr->value.function.name;
2142 else
2143 if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
2144 || se->loop->ss->type == GFC_SS_SCALAR)
2145 name = "unnamed constant";
2148 /* Check lower bound. */
2149 tmp = gfc_conv_array_lbound (descriptor, n);
2150 fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
2151 if (name)
2152 asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
2153 "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
2154 else
2155 asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
2156 gfc_msg_fault, n+1);
2157 gfc_trans_runtime_check (fault, &se->pre, where, msg,
2158 fold_convert (long_integer_type_node, index),
2159 fold_convert (long_integer_type_node, tmp));
2160 gfc_free (msg);
2162 /* Check upper bound. */
2163 if (check_upper)
2165 tmp = gfc_conv_array_ubound (descriptor, n);
2166 fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
2167 if (name)
2168 asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
2169 " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
2170 else
2171 asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
2172 gfc_msg_fault, n+1);
2173 gfc_trans_runtime_check (fault, &se->pre, where, msg,
2174 fold_convert (long_integer_type_node, index),
2175 fold_convert (long_integer_type_node, tmp));
2176 gfc_free (msg);
2179 return index;
2183 /* Return the offset for an index. Performs bound checking for elemental
2184 dimensions. Single element references are processed separately. */
2186 static tree
2187 gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
2188 gfc_array_ref * ar, tree stride)
2190 tree index;
2191 tree desc;
2192 tree data;
2194 /* Get the index into the array for this dimension. */
2195 if (ar)
2197 gcc_assert (ar->type != AR_ELEMENT);
2198 switch (ar->dimen_type[dim])
2200 case DIMEN_ELEMENT:
2201 gcc_assert (i == -1);
2202 /* Elemental dimension. */
2203 gcc_assert (info->subscript[dim]
2204 && info->subscript[dim]->type == GFC_SS_SCALAR);
2205 /* We've already translated this value outside the loop. */
2206 index = info->subscript[dim]->data.scalar.expr;
2208 index = gfc_trans_array_bound_check (se, info->descriptor,
2209 index, dim, &ar->where,
2210 (ar->as->type != AS_ASSUMED_SIZE
2211 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2212 break;
2214 case DIMEN_VECTOR:
2215 gcc_assert (info && se->loop);
2216 gcc_assert (info->subscript[dim]
2217 && info->subscript[dim]->type == GFC_SS_VECTOR);
2218 desc = info->subscript[dim]->data.info.descriptor;
2220 /* Get a zero-based index into the vector. */
2221 index = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2222 se->loop->loopvar[i], se->loop->from[i]);
2224 /* Multiply the index by the stride. */
2225 index = fold_build2 (MULT_EXPR, gfc_array_index_type,
2226 index, gfc_conv_array_stride (desc, 0));
2228 /* Read the vector to get an index into info->descriptor. */
2229 data = build_fold_indirect_ref (gfc_conv_array_data (desc));
2230 index = gfc_build_array_ref (data, index, NULL);
2231 index = gfc_evaluate_now (index, &se->pre);
2233 /* Do any bounds checking on the final info->descriptor index. */
2234 index = gfc_trans_array_bound_check (se, info->descriptor,
2235 index, dim, &ar->where,
2236 (ar->as->type != AS_ASSUMED_SIZE
2237 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2238 break;
2240 case DIMEN_RANGE:
2241 /* Scalarized dimension. */
2242 gcc_assert (info && se->loop);
2244 /* Multiply the loop variable by the stride and delta. */
2245 index = se->loop->loopvar[i];
2246 if (!integer_onep (info->stride[i]))
2247 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index,
2248 info->stride[i]);
2249 if (!integer_zerop (info->delta[i]))
2250 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index,
2251 info->delta[i]);
2252 break;
2254 default:
2255 gcc_unreachable ();
2258 else
2260 /* Temporary array or derived type component. */
2261 gcc_assert (se->loop);
2262 index = se->loop->loopvar[se->loop->order[i]];
2263 if (!integer_zerop (info->delta[i]))
2264 index = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2265 index, info->delta[i]);
2268 /* Multiply by the stride. */
2269 if (!integer_onep (stride))
2270 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index, stride);
2272 return index;
2276 /* Build a scalarized reference to an array. */
2278 static void
2279 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2281 gfc_ss_info *info;
2282 tree decl = NULL_TREE;
2283 tree index;
2284 tree tmp;
2285 int n;
2287 info = &se->ss->data.info;
2288 if (ar)
2289 n = se->loop->order[0];
2290 else
2291 n = 0;
2293 index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
2294 info->stride0);
2295 /* Add the offset for this dimension to the stored offset for all other
2296 dimensions. */
2297 if (!integer_zerop (info->offset))
2298 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset);
2300 if (se->ss->expr && is_subref_array (se->ss->expr))
2301 decl = se->ss->expr->symtree->n.sym->backend_decl;
2303 tmp = build_fold_indirect_ref (info->data);
2304 se->expr = gfc_build_array_ref (tmp, index, decl);
2308 /* Translate access of temporary array. */
2310 void
2311 gfc_conv_tmp_array_ref (gfc_se * se)
2313 se->string_length = se->ss->string_length;
2314 gfc_conv_scalarized_array_ref (se, NULL);
2318 /* Build an array reference. se->expr already holds the array descriptor.
2319 This should be either a variable, indirect variable reference or component
2320 reference. For arrays which do not have a descriptor, se->expr will be
2321 the data pointer.
2322 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2324 void
2325 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2326 locus * where)
2328 int n;
2329 tree index;
2330 tree tmp;
2331 tree stride;
2332 gfc_se indexse;
2334 /* Handle scalarized references separately. */
2335 if (ar->type != AR_ELEMENT)
2337 gfc_conv_scalarized_array_ref (se, ar);
2338 gfc_advance_se_ss_chain (se);
2339 return;
2342 index = gfc_index_zero_node;
2344 /* Calculate the offsets from all the dimensions. */
2345 for (n = 0; n < ar->dimen; n++)
2347 /* Calculate the index for this dimension. */
2348 gfc_init_se (&indexse, se);
2349 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2350 gfc_add_block_to_block (&se->pre, &indexse.pre);
2352 if (flag_bounds_check)
2354 /* Check array bounds. */
2355 tree cond;
2356 char *msg;
2358 /* Evaluate the indexse.expr only once. */
2359 indexse.expr = save_expr (indexse.expr);
2361 /* Lower bound. */
2362 tmp = gfc_conv_array_lbound (se->expr, n);
2363 cond = fold_build2 (LT_EXPR, boolean_type_node,
2364 indexse.expr, tmp);
2365 asprintf (&msg, "%s for array '%s', "
2366 "lower bound of dimension %d exceeded (%%ld < %%ld)",
2367 gfc_msg_fault, sym->name, n+1);
2368 gfc_trans_runtime_check (cond, &se->pre, where, msg,
2369 fold_convert (long_integer_type_node,
2370 indexse.expr),
2371 fold_convert (long_integer_type_node, tmp));
2372 gfc_free (msg);
2374 /* Upper bound, but not for the last dimension of assumed-size
2375 arrays. */
2376 if (n < ar->dimen - 1
2377 || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
2379 tmp = gfc_conv_array_ubound (se->expr, n);
2380 cond = fold_build2 (GT_EXPR, boolean_type_node,
2381 indexse.expr, tmp);
2382 asprintf (&msg, "%s for array '%s', "
2383 "upper bound of dimension %d exceeded (%%ld > %%ld)",
2384 gfc_msg_fault, sym->name, n+1);
2385 gfc_trans_runtime_check (cond, &se->pre, where, msg,
2386 fold_convert (long_integer_type_node,
2387 indexse.expr),
2388 fold_convert (long_integer_type_node, tmp));
2389 gfc_free (msg);
2393 /* Multiply the index by the stride. */
2394 stride = gfc_conv_array_stride (se->expr, n);
2395 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
2396 stride);
2398 /* And add it to the total. */
2399 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2402 tmp = gfc_conv_array_offset (se->expr);
2403 if (!integer_zerop (tmp))
2404 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2406 /* Access the calculated element. */
2407 tmp = gfc_conv_array_data (se->expr);
2408 tmp = build_fold_indirect_ref (tmp);
2409 se->expr = gfc_build_array_ref (tmp, index, sym->backend_decl);
2413 /* Generate the code to be executed immediately before entering a
2414 scalarization loop. */
2416 static void
2417 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2418 stmtblock_t * pblock)
2420 tree index;
2421 tree stride;
2422 gfc_ss_info *info;
2423 gfc_ss *ss;
2424 gfc_se se;
2425 int i;
2427 /* This code will be executed before entering the scalarization loop
2428 for this dimension. */
2429 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2431 if ((ss->useflags & flag) == 0)
2432 continue;
2434 if (ss->type != GFC_SS_SECTION
2435 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2436 && ss->type != GFC_SS_COMPONENT)
2437 continue;
2439 info = &ss->data.info;
2441 if (dim >= info->dimen)
2442 continue;
2444 if (dim == info->dimen - 1)
2446 /* For the outermost loop calculate the offset due to any
2447 elemental dimensions. It will have been initialized with the
2448 base offset of the array. */
2449 if (info->ref)
2451 for (i = 0; i < info->ref->u.ar.dimen; i++)
2453 if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2454 continue;
2456 gfc_init_se (&se, NULL);
2457 se.loop = loop;
2458 se.expr = info->descriptor;
2459 stride = gfc_conv_array_stride (info->descriptor, i);
2460 index = gfc_conv_array_index_offset (&se, info, i, -1,
2461 &info->ref->u.ar,
2462 stride);
2463 gfc_add_block_to_block (pblock, &se.pre);
2465 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2466 info->offset, index);
2467 info->offset = gfc_evaluate_now (info->offset, pblock);
2470 i = loop->order[0];
2471 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2473 else
2474 stride = gfc_conv_array_stride (info->descriptor, 0);
2476 /* Calculate the stride of the innermost loop. Hopefully this will
2477 allow the backend optimizers to do their stuff more effectively.
2479 info->stride0 = gfc_evaluate_now (stride, pblock);
2481 else
2483 /* Add the offset for the previous loop dimension. */
2484 gfc_array_ref *ar;
2486 if (info->ref)
2488 ar = &info->ref->u.ar;
2489 i = loop->order[dim + 1];
2491 else
2493 ar = NULL;
2494 i = dim + 1;
2497 gfc_init_se (&se, NULL);
2498 se.loop = loop;
2499 se.expr = info->descriptor;
2500 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2501 index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
2502 ar, stride);
2503 gfc_add_block_to_block (pblock, &se.pre);
2504 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2505 info->offset, index);
2506 info->offset = gfc_evaluate_now (info->offset, pblock);
2509 /* Remember this offset for the second loop. */
2510 if (dim == loop->temp_dim - 1)
2511 info->saved_offset = info->offset;
2516 /* Start a scalarized expression. Creates a scope and declares loop
2517 variables. */
2519 void
2520 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2522 int dim;
2523 int n;
2524 int flags;
2526 gcc_assert (!loop->array_parameter);
2528 for (dim = loop->dimen - 1; dim >= 0; dim--)
2530 n = loop->order[dim];
2532 gfc_start_block (&loop->code[n]);
2534 /* Create the loop variable. */
2535 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2537 if (dim < loop->temp_dim)
2538 flags = 3;
2539 else
2540 flags = 1;
2541 /* Calculate values that will be constant within this loop. */
2542 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
2544 gfc_start_block (pbody);
2548 /* Generates the actual loop code for a scalarization loop. */
2550 static void
2551 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
2552 stmtblock_t * pbody)
2554 stmtblock_t block;
2555 tree cond;
2556 tree tmp;
2557 tree loopbody;
2558 tree exit_label;
2560 loopbody = gfc_finish_block (pbody);
2562 /* Initialize the loopvar. */
2563 gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]);
2565 exit_label = gfc_build_label_decl (NULL_TREE);
2567 /* Generate the loop body. */
2568 gfc_init_block (&block);
2570 /* The exit condition. */
2571 cond = build2 (GT_EXPR, boolean_type_node, loop->loopvar[n], loop->to[n]);
2572 tmp = build1_v (GOTO_EXPR, exit_label);
2573 TREE_USED (exit_label) = 1;
2574 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
2575 gfc_add_expr_to_block (&block, tmp);
2577 /* The main body. */
2578 gfc_add_expr_to_block (&block, loopbody);
2580 /* Increment the loopvar. */
2581 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
2582 loop->loopvar[n], gfc_index_one_node);
2583 gfc_add_modify_expr (&block, loop->loopvar[n], tmp);
2585 /* Build the loop. */
2586 tmp = gfc_finish_block (&block);
2587 tmp = build1_v (LOOP_EXPR, tmp);
2588 gfc_add_expr_to_block (&loop->code[n], tmp);
2590 /* Add the exit label. */
2591 tmp = build1_v (LABEL_EXPR, exit_label);
2592 gfc_add_expr_to_block (&loop->code[n], tmp);
2596 /* Finishes and generates the loops for a scalarized expression. */
2598 void
2599 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
2601 int dim;
2602 int n;
2603 gfc_ss *ss;
2604 stmtblock_t *pblock;
2605 tree tmp;
2607 pblock = body;
2608 /* Generate the loops. */
2609 for (dim = 0; dim < loop->dimen; dim++)
2611 n = loop->order[dim];
2612 gfc_trans_scalarized_loop_end (loop, n, pblock);
2613 loop->loopvar[n] = NULL_TREE;
2614 pblock = &loop->code[n];
2617 tmp = gfc_finish_block (pblock);
2618 gfc_add_expr_to_block (&loop->pre, tmp);
2620 /* Clear all the used flags. */
2621 for (ss = loop->ss; ss; ss = ss->loop_chain)
2622 ss->useflags = 0;
2626 /* Finish the main body of a scalarized expression, and start the secondary
2627 copying body. */
2629 void
2630 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
2632 int dim;
2633 int n;
2634 stmtblock_t *pblock;
2635 gfc_ss *ss;
2637 pblock = body;
2638 /* We finish as many loops as are used by the temporary. */
2639 for (dim = 0; dim < loop->temp_dim - 1; dim++)
2641 n = loop->order[dim];
2642 gfc_trans_scalarized_loop_end (loop, n, pblock);
2643 loop->loopvar[n] = NULL_TREE;
2644 pblock = &loop->code[n];
2647 /* We don't want to finish the outermost loop entirely. */
2648 n = loop->order[loop->temp_dim - 1];
2649 gfc_trans_scalarized_loop_end (loop, n, pblock);
2651 /* Restore the initial offsets. */
2652 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2654 if ((ss->useflags & 2) == 0)
2655 continue;
2657 if (ss->type != GFC_SS_SECTION
2658 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2659 && ss->type != GFC_SS_COMPONENT)
2660 continue;
2662 ss->data.info.offset = ss->data.info.saved_offset;
2665 /* Restart all the inner loops we just finished. */
2666 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
2668 n = loop->order[dim];
2670 gfc_start_block (&loop->code[n]);
2672 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
2674 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
2677 /* Start a block for the secondary copying code. */
2678 gfc_start_block (body);
2682 /* Calculate the upper bound of an array section. */
2684 static tree
2685 gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
2687 int dim;
2688 gfc_expr *end;
2689 tree desc;
2690 tree bound;
2691 gfc_se se;
2692 gfc_ss_info *info;
2694 gcc_assert (ss->type == GFC_SS_SECTION);
2696 info = &ss->data.info;
2697 dim = info->dim[n];
2699 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2700 /* We'll calculate the upper bound once we have access to the
2701 vector's descriptor. */
2702 return NULL;
2704 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2705 desc = info->descriptor;
2706 end = info->ref->u.ar.end[dim];
2708 if (end)
2710 /* The upper bound was specified. */
2711 gfc_init_se (&se, NULL);
2712 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2713 gfc_add_block_to_block (pblock, &se.pre);
2714 bound = se.expr;
2716 else
2718 /* No upper bound was specified, so use the bound of the array. */
2719 bound = gfc_conv_array_ubound (desc, dim);
2722 return bound;
2726 /* Calculate the lower bound of an array section. */
2728 static void
2729 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
2731 gfc_expr *start;
2732 gfc_expr *end;
2733 gfc_expr *stride;
2734 tree desc;
2735 gfc_se se;
2736 gfc_ss_info *info;
2737 int dim;
2739 gcc_assert (ss->type == GFC_SS_SECTION);
2741 info = &ss->data.info;
2742 dim = info->dim[n];
2744 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2746 /* We use a zero-based index to access the vector. */
2747 info->start[n] = gfc_index_zero_node;
2748 info->end[n] = gfc_index_zero_node;
2749 info->stride[n] = gfc_index_one_node;
2750 return;
2753 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2754 desc = info->descriptor;
2755 start = info->ref->u.ar.start[dim];
2756 end = info->ref->u.ar.end[dim];
2757 stride = info->ref->u.ar.stride[dim];
2759 /* Calculate the start of the range. For vector subscripts this will
2760 be the range of the vector. */
2761 if (start)
2763 /* Specified section start. */
2764 gfc_init_se (&se, NULL);
2765 gfc_conv_expr_type (&se, start, gfc_array_index_type);
2766 gfc_add_block_to_block (&loop->pre, &se.pre);
2767 info->start[n] = se.expr;
2769 else
2771 /* No lower bound specified so use the bound of the array. */
2772 info->start[n] = gfc_conv_array_lbound (desc, dim);
2774 info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
2776 /* Similarly calculate the end. Although this is not used in the
2777 scalarizer, it is needed when checking bounds and where the end
2778 is an expression with side-effects. */
2779 if (end)
2781 /* Specified section start. */
2782 gfc_init_se (&se, NULL);
2783 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2784 gfc_add_block_to_block (&loop->pre, &se.pre);
2785 info->end[n] = se.expr;
2787 else
2789 /* No upper bound specified so use the bound of the array. */
2790 info->end[n] = gfc_conv_array_ubound (desc, dim);
2792 info->end[n] = gfc_evaluate_now (info->end[n], &loop->pre);
2794 /* Calculate the stride. */
2795 if (stride == NULL)
2796 info->stride[n] = gfc_index_one_node;
2797 else
2799 gfc_init_se (&se, NULL);
2800 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
2801 gfc_add_block_to_block (&loop->pre, &se.pre);
2802 info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
2807 /* Calculates the range start and stride for a SS chain. Also gets the
2808 descriptor and data pointer. The range of vector subscripts is the size
2809 of the vector. Array bounds are also checked. */
2811 void
2812 gfc_conv_ss_startstride (gfc_loopinfo * loop)
2814 int n;
2815 tree tmp;
2816 gfc_ss *ss;
2817 tree desc;
2819 loop->dimen = 0;
2820 /* Determine the rank of the loop. */
2821 for (ss = loop->ss;
2822 ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
2824 switch (ss->type)
2826 case GFC_SS_SECTION:
2827 case GFC_SS_CONSTRUCTOR:
2828 case GFC_SS_FUNCTION:
2829 case GFC_SS_COMPONENT:
2830 loop->dimen = ss->data.info.dimen;
2831 break;
2833 /* As usual, lbound and ubound are exceptions!. */
2834 case GFC_SS_INTRINSIC:
2835 switch (ss->expr->value.function.isym->id)
2837 case GFC_ISYM_LBOUND:
2838 case GFC_ISYM_UBOUND:
2839 loop->dimen = ss->data.info.dimen;
2841 default:
2842 break;
2845 default:
2846 break;
2850 /* We should have determined the rank of the expression by now. If
2851 not, that's bad news. */
2852 gcc_assert (loop->dimen != 0);
2854 /* Loop over all the SS in the chain. */
2855 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2857 if (ss->expr && ss->expr->shape && !ss->shape)
2858 ss->shape = ss->expr->shape;
2860 switch (ss->type)
2862 case GFC_SS_SECTION:
2863 /* Get the descriptor for the array. */
2864 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
2866 for (n = 0; n < ss->data.info.dimen; n++)
2867 gfc_conv_section_startstride (loop, ss, n);
2868 break;
2870 case GFC_SS_INTRINSIC:
2871 switch (ss->expr->value.function.isym->id)
2873 /* Fall through to supply start and stride. */
2874 case GFC_ISYM_LBOUND:
2875 case GFC_ISYM_UBOUND:
2876 break;
2877 default:
2878 continue;
2881 case GFC_SS_CONSTRUCTOR:
2882 case GFC_SS_FUNCTION:
2883 for (n = 0; n < ss->data.info.dimen; n++)
2885 ss->data.info.start[n] = gfc_index_zero_node;
2886 ss->data.info.end[n] = gfc_index_zero_node;
2887 ss->data.info.stride[n] = gfc_index_one_node;
2889 break;
2891 default:
2892 break;
2896 /* The rest is just runtime bound checking. */
2897 if (flag_bounds_check)
2899 stmtblock_t block;
2900 tree lbound, ubound;
2901 tree end;
2902 tree size[GFC_MAX_DIMENSIONS];
2903 tree stride_pos, stride_neg, non_zerosized, tmp2;
2904 gfc_ss_info *info;
2905 char *msg;
2906 int dim;
2908 gfc_start_block (&block);
2910 for (n = 0; n < loop->dimen; n++)
2911 size[n] = NULL_TREE;
2913 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2915 if (ss->type != GFC_SS_SECTION)
2916 continue;
2918 /* TODO: range checking for mapped dimensions. */
2919 info = &ss->data.info;
2921 /* This code only checks ranges. Elemental and vector
2922 dimensions are checked later. */
2923 for (n = 0; n < loop->dimen; n++)
2925 bool check_upper;
2927 dim = info->dim[n];
2928 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
2929 continue;
2931 if (dim == info->ref->u.ar.dimen - 1
2932 && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
2933 || info->ref->u.ar.as->cp_was_assumed))
2934 check_upper = false;
2935 else
2936 check_upper = true;
2938 /* Zero stride is not allowed. */
2939 tmp = fold_build2 (EQ_EXPR, boolean_type_node, info->stride[n],
2940 gfc_index_zero_node);
2941 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
2942 "of array '%s'", info->dim[n]+1,
2943 ss->expr->symtree->name);
2944 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg);
2945 gfc_free (msg);
2947 desc = ss->data.info.descriptor;
2949 /* This is the run-time equivalent of resolve.c's
2950 check_dimension(). The logical is more readable there
2951 than it is here, with all the trees. */
2952 lbound = gfc_conv_array_lbound (desc, dim);
2953 end = info->end[n];
2954 if (check_upper)
2955 ubound = gfc_conv_array_ubound (desc, dim);
2956 else
2957 ubound = NULL;
2959 /* non_zerosized is true when the selected range is not
2960 empty. */
2961 stride_pos = fold_build2 (GT_EXPR, boolean_type_node,
2962 info->stride[n], gfc_index_zero_node);
2963 tmp = fold_build2 (LE_EXPR, boolean_type_node, info->start[n],
2964 end);
2965 stride_pos = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2966 stride_pos, tmp);
2968 stride_neg = fold_build2 (LT_EXPR, boolean_type_node,
2969 info->stride[n], gfc_index_zero_node);
2970 tmp = fold_build2 (GE_EXPR, boolean_type_node, info->start[n],
2971 end);
2972 stride_neg = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2973 stride_neg, tmp);
2974 non_zerosized = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
2975 stride_pos, stride_neg);
2977 /* Check the start of the range against the lower and upper
2978 bounds of the array, if the range is not empty. */
2979 tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
2980 lbound);
2981 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2982 non_zerosized, tmp);
2983 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
2984 " exceeded (%%ld < %%ld)", gfc_msg_fault,
2985 info->dim[n]+1, ss->expr->symtree->name);
2986 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
2987 fold_convert (long_integer_type_node,
2988 info->start[n]),
2989 fold_convert (long_integer_type_node,
2990 lbound));
2991 gfc_free (msg);
2993 if (check_upper)
2995 tmp = fold_build2 (GT_EXPR, boolean_type_node,
2996 info->start[n], ubound);
2997 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
2998 non_zerosized, tmp);
2999 asprintf (&msg, "%s, upper bound of dimension %d of array "
3000 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3001 info->dim[n]+1, ss->expr->symtree->name);
3002 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
3003 fold_convert (long_integer_type_node, info->start[n]),
3004 fold_convert (long_integer_type_node, ubound));
3005 gfc_free (msg);
3008 /* Compute the last element of the range, which is not
3009 necessarily "end" (think 0:5:3, which doesn't contain 5)
3010 and check it against both lower and upper bounds. */
3011 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3012 info->start[n]);
3013 tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
3014 info->stride[n]);
3015 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3016 tmp2);
3018 tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
3019 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3020 non_zerosized, tmp);
3021 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
3022 " exceeded (%%ld < %%ld)", gfc_msg_fault,
3023 info->dim[n]+1, ss->expr->symtree->name);
3024 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
3025 fold_convert (long_integer_type_node,
3026 tmp2),
3027 fold_convert (long_integer_type_node,
3028 lbound));
3029 gfc_free (msg);
3031 if (check_upper)
3033 tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
3034 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3035 non_zerosized, tmp);
3036 asprintf (&msg, "%s, upper bound of dimension %d of array "
3037 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3038 info->dim[n]+1, ss->expr->symtree->name);
3039 gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
3040 fold_convert (long_integer_type_node, tmp2),
3041 fold_convert (long_integer_type_node, ubound));
3042 gfc_free (msg);
3045 /* Check the section sizes match. */
3046 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3047 info->start[n]);
3048 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
3049 info->stride[n]);
3050 /* We remember the size of the first section, and check all the
3051 others against this. */
3052 if (size[n])
3054 tree tmp3;
3056 tmp3 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
3058 /* For optional arguments, only check bounds if the
3059 argument is present. */
3060 if (ss->expr->symtree->n.sym->attr.optional
3061 || ss->expr->symtree->n.sym->attr.not_always_present)
3063 tree cond;
3065 cond = gfc_conv_expr_present (ss->expr->symtree->n.sym);
3066 tmp3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3067 cond, tmp3);
3070 asprintf (&msg, "%s, size mismatch for dimension %d "
3071 "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
3072 info->dim[n]+1, ss->expr->symtree->name);
3073 gfc_trans_runtime_check (tmp3, &block, &ss->expr->where, msg,
3074 fold_convert (long_integer_type_node, tmp),
3075 fold_convert (long_integer_type_node, size[n]));
3076 gfc_free (msg);
3078 else
3079 size[n] = gfc_evaluate_now (tmp, &block);
3083 tmp = gfc_finish_block (&block);
3084 gfc_add_expr_to_block (&loop->pre, tmp);
3089 /* Return true if the two SS could be aliased, i.e. both point to the same data
3090 object. */
3091 /* TODO: resolve aliases based on frontend expressions. */
3093 static int
3094 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
3096 gfc_ref *lref;
3097 gfc_ref *rref;
3098 gfc_symbol *lsym;
3099 gfc_symbol *rsym;
3101 lsym = lss->expr->symtree->n.sym;
3102 rsym = rss->expr->symtree->n.sym;
3103 if (gfc_symbols_could_alias (lsym, rsym))
3104 return 1;
3106 if (rsym->ts.type != BT_DERIVED
3107 && lsym->ts.type != BT_DERIVED)
3108 return 0;
3110 /* For derived types we must check all the component types. We can ignore
3111 array references as these will have the same base type as the previous
3112 component ref. */
3113 for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
3115 if (lref->type != REF_COMPONENT)
3116 continue;
3118 if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
3119 return 1;
3121 for (rref = rss->expr->ref; rref != rss->data.info.ref;
3122 rref = rref->next)
3124 if (rref->type != REF_COMPONENT)
3125 continue;
3127 if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
3128 return 1;
3132 for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
3134 if (rref->type != REF_COMPONENT)
3135 break;
3137 if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
3138 return 1;
3141 return 0;
3145 /* Resolve array data dependencies. Creates a temporary if required. */
3146 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
3147 dependency.c. */
3149 void
3150 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
3151 gfc_ss * rss)
3153 gfc_ss *ss;
3154 gfc_ref *lref;
3155 gfc_ref *rref;
3156 gfc_ref *aref;
3157 int nDepend = 0;
3158 int temp_dim = 0;
3160 loop->temp_ss = NULL;
3161 aref = dest->data.info.ref;
3162 temp_dim = 0;
3164 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
3166 if (ss->type != GFC_SS_SECTION)
3167 continue;
3169 if (gfc_could_be_alias (dest, ss)
3170 || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3172 nDepend = 1;
3173 break;
3176 if (dest->expr->symtree->n.sym == ss->expr->symtree->n.sym)
3178 lref = dest->expr->ref;
3179 rref = ss->expr->ref;
3181 nDepend = gfc_dep_resolver (lref, rref);
3182 if (nDepend == 1)
3183 break;
3184 #if 0
3185 /* TODO : loop shifting. */
3186 if (nDepend == 1)
3188 /* Mark the dimensions for LOOP SHIFTING */
3189 for (n = 0; n < loop->dimen; n++)
3191 int dim = dest->data.info.dim[n];
3193 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3194 depends[n] = 2;
3195 else if (! gfc_is_same_range (&lref->u.ar,
3196 &rref->u.ar, dim, 0))
3197 depends[n] = 1;
3200 /* Put all the dimensions with dependencies in the
3201 innermost loops. */
3202 dim = 0;
3203 for (n = 0; n < loop->dimen; n++)
3205 gcc_assert (loop->order[n] == n);
3206 if (depends[n])
3207 loop->order[dim++] = n;
3209 temp_dim = dim;
3210 for (n = 0; n < loop->dimen; n++)
3212 if (! depends[n])
3213 loop->order[dim++] = n;
3216 gcc_assert (dim == loop->dimen);
3217 break;
3219 #endif
3223 if (nDepend == 1)
3225 tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
3226 if (GFC_ARRAY_TYPE_P (base_type)
3227 || GFC_DESCRIPTOR_TYPE_P (base_type))
3228 base_type = gfc_get_element_type (base_type);
3229 loop->temp_ss = gfc_get_ss ();
3230 loop->temp_ss->type = GFC_SS_TEMP;
3231 loop->temp_ss->data.temp.type = base_type;
3232 loop->temp_ss->string_length = dest->string_length;
3233 loop->temp_ss->data.temp.dimen = loop->dimen;
3234 loop->temp_ss->next = gfc_ss_terminator;
3235 gfc_add_ss_to_loop (loop, loop->temp_ss);
3237 else
3238 loop->temp_ss = NULL;
3242 /* Initialize the scalarization loop. Creates the loop variables. Determines
3243 the range of the loop variables. Creates a temporary if required.
3244 Calculates how to transform from loop variables to array indices for each
3245 expression. Also generates code for scalar expressions which have been
3246 moved outside the loop. */
3248 void
3249 gfc_conv_loop_setup (gfc_loopinfo * loop)
3251 int n;
3252 int dim;
3253 gfc_ss_info *info;
3254 gfc_ss_info *specinfo;
3255 gfc_ss *ss;
3256 tree tmp;
3257 tree len;
3258 gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
3259 bool dynamic[GFC_MAX_DIMENSIONS];
3260 gfc_constructor *c;
3261 mpz_t *cshape;
3262 mpz_t i;
3264 mpz_init (i);
3265 for (n = 0; n < loop->dimen; n++)
3267 loopspec[n] = NULL;
3268 dynamic[n] = false;
3269 /* We use one SS term, and use that to determine the bounds of the
3270 loop for this dimension. We try to pick the simplest term. */
3271 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3273 if (ss->shape)
3275 /* The frontend has worked out the size for us. */
3276 loopspec[n] = ss;
3277 continue;
3280 if (ss->type == GFC_SS_CONSTRUCTOR)
3282 /* An unknown size constructor will always be rank one.
3283 Higher rank constructors will either have known shape,
3284 or still be wrapped in a call to reshape. */
3285 gcc_assert (loop->dimen == 1);
3287 /* Always prefer to use the constructor bounds if the size
3288 can be determined at compile time. Prefer not to otherwise,
3289 since the general case involves realloc, and it's better to
3290 avoid that overhead if possible. */
3291 c = ss->expr->value.constructor;
3292 dynamic[n] = gfc_get_array_constructor_size (&i, c);
3293 if (!dynamic[n] || !loopspec[n])
3294 loopspec[n] = ss;
3295 continue;
3298 /* TODO: Pick the best bound if we have a choice between a
3299 function and something else. */
3300 if (ss->type == GFC_SS_FUNCTION)
3302 loopspec[n] = ss;
3303 continue;
3306 if (ss->type != GFC_SS_SECTION)
3307 continue;
3309 if (loopspec[n])
3310 specinfo = &loopspec[n]->data.info;
3311 else
3312 specinfo = NULL;
3313 info = &ss->data.info;
3315 if (!specinfo)
3316 loopspec[n] = ss;
3317 /* Criteria for choosing a loop specifier (most important first):
3318 doesn't need realloc
3319 stride of one
3320 known stride
3321 known lower bound
3322 known upper bound
3324 else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
3325 loopspec[n] = ss;
3326 else if (integer_onep (info->stride[n])
3327 && !integer_onep (specinfo->stride[n]))
3328 loopspec[n] = ss;
3329 else if (INTEGER_CST_P (info->stride[n])
3330 && !INTEGER_CST_P (specinfo->stride[n]))
3331 loopspec[n] = ss;
3332 else if (INTEGER_CST_P (info->start[n])
3333 && !INTEGER_CST_P (specinfo->start[n]))
3334 loopspec[n] = ss;
3335 /* We don't work out the upper bound.
3336 else if (INTEGER_CST_P (info->finish[n])
3337 && ! INTEGER_CST_P (specinfo->finish[n]))
3338 loopspec[n] = ss; */
3341 /* We should have found the scalarization loop specifier. If not,
3342 that's bad news. */
3343 gcc_assert (loopspec[n]);
3345 info = &loopspec[n]->data.info;
3347 /* Set the extents of this range. */
3348 cshape = loopspec[n]->shape;
3349 if (cshape && INTEGER_CST_P (info->start[n])
3350 && INTEGER_CST_P (info->stride[n]))
3352 loop->from[n] = info->start[n];
3353 mpz_set (i, cshape[n]);
3354 mpz_sub_ui (i, i, 1);
3355 /* To = from + (size - 1) * stride. */
3356 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
3357 if (!integer_onep (info->stride[n]))
3358 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3359 tmp, info->stride[n]);
3360 loop->to[n] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3361 loop->from[n], tmp);
3363 else
3365 loop->from[n] = info->start[n];
3366 switch (loopspec[n]->type)
3368 case GFC_SS_CONSTRUCTOR:
3369 /* The upper bound is calculated when we expand the
3370 constructor. */
3371 gcc_assert (loop->to[n] == NULL_TREE);
3372 break;
3374 case GFC_SS_SECTION:
3375 loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
3376 &loop->pre);
3377 break;
3379 case GFC_SS_FUNCTION:
3380 /* The loop bound will be set when we generate the call. */
3381 gcc_assert (loop->to[n] == NULL_TREE);
3382 break;
3384 default:
3385 gcc_unreachable ();
3389 /* Transform everything so we have a simple incrementing variable. */
3390 if (integer_onep (info->stride[n]))
3391 info->delta[n] = gfc_index_zero_node;
3392 else
3394 /* Set the delta for this section. */
3395 info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
3396 /* Number of iterations is (end - start + step) / step.
3397 with start = 0, this simplifies to
3398 last = end / step;
3399 for (i = 0; i<=last; i++){...}; */
3400 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3401 loop->to[n], loop->from[n]);
3402 tmp = fold_build2 (TRUNC_DIV_EXPR, gfc_array_index_type,
3403 tmp, info->stride[n]);
3404 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
3405 /* Make the loop variable start at 0. */
3406 loop->from[n] = gfc_index_zero_node;
3410 /* Add all the scalar code that can be taken out of the loops.
3411 This may include calculating the loop bounds, so do it before
3412 allocating the temporary. */
3413 gfc_add_loop_ss_code (loop, loop->ss, false);
3415 /* If we want a temporary then create it. */
3416 if (loop->temp_ss != NULL)
3418 gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
3420 /* Make absolutely sure that this is a complete type. */
3421 if (loop->temp_ss->string_length)
3422 loop->temp_ss->data.temp.type
3423 = gfc_get_character_type_len (gfc_default_character_kind,
3424 loop->temp_ss->string_length);
3426 tmp = loop->temp_ss->data.temp.type;
3427 len = loop->temp_ss->string_length;
3428 n = loop->temp_ss->data.temp.dimen;
3429 memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
3430 loop->temp_ss->type = GFC_SS_SECTION;
3431 loop->temp_ss->data.info.dimen = n;
3432 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
3433 &loop->temp_ss->data.info, tmp, false, true,
3434 false);
3437 for (n = 0; n < loop->temp_dim; n++)
3438 loopspec[loop->order[n]] = NULL;
3440 mpz_clear (i);
3442 /* For array parameters we don't have loop variables, so don't calculate the
3443 translations. */
3444 if (loop->array_parameter)
3445 return;
3447 /* Calculate the translation from loop variables to array indices. */
3448 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3450 if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT)
3451 continue;
3453 info = &ss->data.info;
3455 for (n = 0; n < info->dimen; n++)
3457 dim = info->dim[n];
3459 /* If we are specifying the range the delta is already set. */
3460 if (loopspec[n] != ss)
3462 /* Calculate the offset relative to the loop variable.
3463 First multiply by the stride. */
3464 tmp = loop->from[n];
3465 if (!integer_onep (info->stride[n]))
3466 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3467 tmp, info->stride[n]);
3469 /* Then subtract this from our starting value. */
3470 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3471 info->start[n], tmp);
3473 info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
3480 /* Fills in an array descriptor, and returns the size of the array. The size
3481 will be a simple_val, ie a variable or a constant. Also calculates the
3482 offset of the base. Returns the size of the array.
3484 stride = 1;
3485 offset = 0;
3486 for (n = 0; n < rank; n++)
3488 a.lbound[n] = specified_lower_bound;
3489 offset = offset + a.lbond[n] * stride;
3490 size = 1 - lbound;
3491 a.ubound[n] = specified_upper_bound;
3492 a.stride[n] = stride;
3493 size = ubound + size; //size = ubound + 1 - lbound
3494 stride = stride * size;
3496 return (stride);
3497 } */
3498 /*GCC ARRAYS*/
3500 static tree
3501 gfc_array_init_size (tree descriptor, int rank, tree * poffset,
3502 gfc_expr ** lower, gfc_expr ** upper,
3503 stmtblock_t * pblock)
3505 tree type;
3506 tree tmp;
3507 tree size;
3508 tree offset;
3509 tree stride;
3510 tree cond;
3511 tree or_expr;
3512 tree thencase;
3513 tree elsecase;
3514 tree var;
3515 stmtblock_t thenblock;
3516 stmtblock_t elseblock;
3517 gfc_expr *ubound;
3518 gfc_se se;
3519 int n;
3521 type = TREE_TYPE (descriptor);
3523 stride = gfc_index_one_node;
3524 offset = gfc_index_zero_node;
3526 /* Set the dtype. */
3527 tmp = gfc_conv_descriptor_dtype (descriptor);
3528 gfc_add_modify_expr (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
3530 or_expr = NULL_TREE;
3532 for (n = 0; n < rank; n++)
3534 /* We have 3 possibilities for determining the size of the array:
3535 lower == NULL => lbound = 1, ubound = upper[n]
3536 upper[n] = NULL => lbound = 1, ubound = lower[n]
3537 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
3538 ubound = upper[n];
3540 /* Set lower bound. */
3541 gfc_init_se (&se, NULL);
3542 if (lower == NULL)
3543 se.expr = gfc_index_one_node;
3544 else
3546 gcc_assert (lower[n]);
3547 if (ubound)
3549 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
3550 gfc_add_block_to_block (pblock, &se.pre);
3552 else
3554 se.expr = gfc_index_one_node;
3555 ubound = lower[n];
3558 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
3559 gfc_add_modify_expr (pblock, tmp, se.expr);
3561 /* Work out the offset for this component. */
3562 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
3563 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3565 /* Start the calculation for the size of this dimension. */
3566 size = build2 (MINUS_EXPR, gfc_array_index_type,
3567 gfc_index_one_node, se.expr);
3569 /* Set upper bound. */
3570 gfc_init_se (&se, NULL);
3571 gcc_assert (ubound);
3572 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
3573 gfc_add_block_to_block (pblock, &se.pre);
3575 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
3576 gfc_add_modify_expr (pblock, tmp, se.expr);
3578 /* Store the stride. */
3579 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
3580 gfc_add_modify_expr (pblock, tmp, stride);
3582 /* Calculate the size of this dimension. */
3583 size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
3585 /* Check whether the size for this dimension is negative. */
3586 cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3587 gfc_index_zero_node);
3588 if (n == 0)
3589 or_expr = cond;
3590 else
3591 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
3593 /* Multiply the stride by the number of elements in this dimension. */
3594 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, size);
3595 stride = gfc_evaluate_now (stride, pblock);
3598 /* The stride is the number of elements in the array, so multiply by the
3599 size of an element to get the total size. */
3600 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3601 size = fold_build2 (MULT_EXPR, gfc_array_index_type, stride,
3602 fold_convert (gfc_array_index_type, tmp));
3604 if (poffset != NULL)
3606 offset = gfc_evaluate_now (offset, pblock);
3607 *poffset = offset;
3610 if (integer_zerop (or_expr))
3611 return size;
3612 if (integer_onep (or_expr))
3613 return gfc_index_zero_node;
3615 var = gfc_create_var (TREE_TYPE (size), "size");
3616 gfc_start_block (&thenblock);
3617 gfc_add_modify_expr (&thenblock, var, gfc_index_zero_node);
3618 thencase = gfc_finish_block (&thenblock);
3620 gfc_start_block (&elseblock);
3621 gfc_add_modify_expr (&elseblock, var, size);
3622 elsecase = gfc_finish_block (&elseblock);
3624 tmp = gfc_evaluate_now (or_expr, pblock);
3625 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
3626 gfc_add_expr_to_block (pblock, tmp);
3628 return var;
3632 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
3633 the work for an ALLOCATE statement. */
3634 /*GCC ARRAYS*/
3636 bool
3637 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
3639 tree tmp;
3640 tree pointer;
3641 tree offset;
3642 tree size;
3643 gfc_expr **lower;
3644 gfc_expr **upper;
3645 gfc_ref *ref, *prev_ref = NULL;
3646 bool allocatable_array;
3648 ref = expr->ref;
3650 /* Find the last reference in the chain. */
3651 while (ref && ref->next != NULL)
3653 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
3654 prev_ref = ref;
3655 ref = ref->next;
3658 if (ref == NULL || ref->type != REF_ARRAY)
3659 return false;
3661 if (!prev_ref)
3662 allocatable_array = expr->symtree->n.sym->attr.allocatable;
3663 else
3664 allocatable_array = prev_ref->u.c.component->allocatable;
3666 /* Figure out the size of the array. */
3667 switch (ref->u.ar.type)
3669 case AR_ELEMENT:
3670 lower = NULL;
3671 upper = ref->u.ar.start;
3672 break;
3674 case AR_FULL:
3675 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
3677 lower = ref->u.ar.as->lower;
3678 upper = ref->u.ar.as->upper;
3679 break;
3681 case AR_SECTION:
3682 lower = ref->u.ar.start;
3683 upper = ref->u.ar.end;
3684 break;
3686 default:
3687 gcc_unreachable ();
3688 break;
3691 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
3692 lower, upper, &se->pre);
3694 /* Allocate memory to store the data. */
3695 pointer = gfc_conv_descriptor_data_get (se->expr);
3696 STRIP_NOPS (pointer);
3698 /* The allocate_array variants take the old pointer as first argument. */
3699 if (allocatable_array)
3700 tmp = gfc_allocate_array_with_status (&se->pre, pointer, size, pstat);
3701 else
3702 tmp = gfc_allocate_with_status (&se->pre, size, pstat);
3703 tmp = build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
3704 gfc_add_expr_to_block (&se->pre, tmp);
3706 tmp = gfc_conv_descriptor_offset (se->expr);
3707 gfc_add_modify_expr (&se->pre, tmp, offset);
3709 if (expr->ts.type == BT_DERIVED
3710 && expr->ts.derived->attr.alloc_comp)
3712 tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
3713 ref->u.ar.as->rank);
3714 gfc_add_expr_to_block (&se->pre, tmp);
3717 return true;
3721 /* Deallocate an array variable. Also used when an allocated variable goes
3722 out of scope. */
3723 /*GCC ARRAYS*/
3725 tree
3726 gfc_array_deallocate (tree descriptor, tree pstat)
3728 tree var;
3729 tree tmp;
3730 stmtblock_t block;
3732 gfc_start_block (&block);
3733 /* Get a pointer to the data. */
3734 var = gfc_conv_descriptor_data_get (descriptor);
3735 STRIP_NOPS (var);
3737 /* Parameter is the address of the data component. */
3738 tmp = gfc_deallocate_with_status (var, pstat, false);
3739 gfc_add_expr_to_block (&block, tmp);
3741 /* Zero the data pointer. */
3742 tmp = build2 (MODIFY_EXPR, void_type_node,
3743 var, build_int_cst (TREE_TYPE (var), 0));
3744 gfc_add_expr_to_block (&block, tmp);
3746 return gfc_finish_block (&block);
3750 /* Create an array constructor from an initialization expression.
3751 We assume the frontend already did any expansions and conversions. */
3753 tree
3754 gfc_conv_array_initializer (tree type, gfc_expr * expr)
3756 gfc_constructor *c;
3757 tree tmp;
3758 mpz_t maxval;
3759 gfc_se se;
3760 HOST_WIDE_INT hi;
3761 unsigned HOST_WIDE_INT lo;
3762 tree index, range;
3763 VEC(constructor_elt,gc) *v = NULL;
3765 switch (expr->expr_type)
3767 case EXPR_CONSTANT:
3768 case EXPR_STRUCTURE:
3769 /* A single scalar or derived type value. Create an array with all
3770 elements equal to that value. */
3771 gfc_init_se (&se, NULL);
3773 if (expr->expr_type == EXPR_CONSTANT)
3774 gfc_conv_constant (&se, expr);
3775 else
3776 gfc_conv_structure (&se, expr, 1);
3778 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
3779 gcc_assert (tmp && INTEGER_CST_P (tmp));
3780 hi = TREE_INT_CST_HIGH (tmp);
3781 lo = TREE_INT_CST_LOW (tmp);
3782 lo++;
3783 if (lo == 0)
3784 hi++;
3785 /* This will probably eat buckets of memory for large arrays. */
3786 while (hi != 0 || lo != 0)
3788 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
3789 if (lo == 0)
3790 hi--;
3791 lo--;
3793 break;
3795 case EXPR_ARRAY:
3796 /* Create a vector of all the elements. */
3797 for (c = expr->value.constructor; c; c = c->next)
3799 if (c->iterator)
3801 /* Problems occur when we get something like
3802 integer :: a(lots) = (/(i, i=1,lots)/) */
3803 /* TODO: Unexpanded array initializers. */
3804 internal_error
3805 ("Possible frontend bug: array constructor not expanded");
3807 if (mpz_cmp_si (c->n.offset, 0) != 0)
3808 index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3809 else
3810 index = NULL_TREE;
3811 mpz_init (maxval);
3812 if (mpz_cmp_si (c->repeat, 0) != 0)
3814 tree tmp1, tmp2;
3816 mpz_set (maxval, c->repeat);
3817 mpz_add (maxval, c->n.offset, maxval);
3818 mpz_sub_ui (maxval, maxval, 1);
3819 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3820 if (mpz_cmp_si (c->n.offset, 0) != 0)
3822 mpz_add_ui (maxval, c->n.offset, 1);
3823 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3825 else
3826 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3828 range = build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
3830 else
3831 range = NULL;
3832 mpz_clear (maxval);
3834 gfc_init_se (&se, NULL);
3835 switch (c->expr->expr_type)
3837 case EXPR_CONSTANT:
3838 gfc_conv_constant (&se, c->expr);
3839 if (range == NULL_TREE)
3840 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3841 else
3843 if (index != NULL_TREE)
3844 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3845 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
3847 break;
3849 case EXPR_STRUCTURE:
3850 gfc_conv_structure (&se, c->expr, 1);
3851 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3852 break;
3854 default:
3855 gcc_unreachable ();
3858 break;
3860 case EXPR_NULL:
3861 return gfc_build_null_descriptor (type);
3863 default:
3864 gcc_unreachable ();
3867 /* Create a constructor from the list of elements. */
3868 tmp = build_constructor (type, v);
3869 TREE_CONSTANT (tmp) = 1;
3870 TREE_INVARIANT (tmp) = 1;
3871 return tmp;
3875 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
3876 returns the size (in elements) of the array. */
3878 static tree
3879 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
3880 stmtblock_t * pblock)
3882 gfc_array_spec *as;
3883 tree size;
3884 tree stride;
3885 tree offset;
3886 tree ubound;
3887 tree lbound;
3888 tree tmp;
3889 gfc_se se;
3891 int dim;
3893 as = sym->as;
3895 size = gfc_index_one_node;
3896 offset = gfc_index_zero_node;
3897 for (dim = 0; dim < as->rank; dim++)
3899 /* Evaluate non-constant array bound expressions. */
3900 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
3901 if (as->lower[dim] && !INTEGER_CST_P (lbound))
3903 gfc_init_se (&se, NULL);
3904 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
3905 gfc_add_block_to_block (pblock, &se.pre);
3906 gfc_add_modify_expr (pblock, lbound, se.expr);
3908 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
3909 if (as->upper[dim] && !INTEGER_CST_P (ubound))
3911 gfc_init_se (&se, NULL);
3912 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
3913 gfc_add_block_to_block (pblock, &se.pre);
3914 gfc_add_modify_expr (pblock, ubound, se.expr);
3916 /* The offset of this dimension. offset = offset - lbound * stride. */
3917 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, size);
3918 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3920 /* The size of this dimension, and the stride of the next. */
3921 if (dim + 1 < as->rank)
3922 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
3923 else
3924 stride = GFC_TYPE_ARRAY_SIZE (type);
3926 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
3928 /* Calculate stride = size * (ubound + 1 - lbound). */
3929 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3930 gfc_index_one_node, lbound);
3931 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp);
3932 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
3933 if (stride)
3934 gfc_add_modify_expr (pblock, stride, tmp);
3935 else
3936 stride = gfc_evaluate_now (tmp, pblock);
3938 /* Make sure that negative size arrays are translated
3939 to being zero size. */
3940 tmp = build2 (GE_EXPR, boolean_type_node,
3941 stride, gfc_index_zero_node);
3942 tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
3943 stride, gfc_index_zero_node);
3944 gfc_add_modify_expr (pblock, stride, tmp);
3947 size = stride;
3950 gfc_trans_vla_type_sizes (sym, pblock);
3952 *poffset = offset;
3953 return size;
3957 /* Generate code to initialize/allocate an array variable. */
3959 tree
3960 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
3962 stmtblock_t block;
3963 tree type;
3964 tree tmp;
3965 tree size;
3966 tree offset;
3967 bool onstack;
3969 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
3971 /* Do nothing for USEd variables. */
3972 if (sym->attr.use_assoc)
3973 return fnbody;
3975 type = TREE_TYPE (decl);
3976 gcc_assert (GFC_ARRAY_TYPE_P (type));
3977 onstack = TREE_CODE (type) != POINTER_TYPE;
3979 gfc_start_block (&block);
3981 /* Evaluate character string length. */
3982 if (sym->ts.type == BT_CHARACTER
3983 && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3985 gfc_conv_string_length (sym->ts.cl, &block);
3987 gfc_trans_vla_type_sizes (sym, &block);
3989 /* Emit a DECL_EXPR for this variable, which will cause the
3990 gimplifier to allocate storage, and all that good stuff. */
3991 tmp = build1 (DECL_EXPR, TREE_TYPE (decl), decl);
3992 gfc_add_expr_to_block (&block, tmp);
3995 if (onstack)
3997 gfc_add_expr_to_block (&block, fnbody);
3998 return gfc_finish_block (&block);
4001 type = TREE_TYPE (type);
4003 gcc_assert (!sym->attr.use_assoc);
4004 gcc_assert (!TREE_STATIC (decl));
4005 gcc_assert (!sym->module);
4007 if (sym->ts.type == BT_CHARACTER
4008 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4009 gfc_conv_string_length (sym->ts.cl, &block);
4011 size = gfc_trans_array_bounds (type, sym, &offset, &block);
4013 /* Don't actually allocate space for Cray Pointees. */
4014 if (sym->attr.cray_pointee)
4016 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4017 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4018 gfc_add_expr_to_block (&block, fnbody);
4019 return gfc_finish_block (&block);
4022 /* The size is the number of elements in the array, so multiply by the
4023 size of an element to get the total size. */
4024 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4025 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
4026 fold_convert (gfc_array_index_type, tmp));
4028 /* Allocate memory to hold the data. */
4029 tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
4030 gfc_add_modify_expr (&block, decl, tmp);
4032 /* Set offset of the array. */
4033 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4034 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4037 /* Automatic arrays should not have initializers. */
4038 gcc_assert (!sym->value);
4040 gfc_add_expr_to_block (&block, fnbody);
4042 /* Free the temporary. */
4043 tmp = gfc_call_free (convert (pvoid_type_node, decl));
4044 gfc_add_expr_to_block (&block, tmp);
4046 return gfc_finish_block (&block);
4050 /* Generate entry and exit code for g77 calling convention arrays. */
4052 tree
4053 gfc_trans_g77_array (gfc_symbol * sym, tree body)
4055 tree parm;
4056 tree type;
4057 locus loc;
4058 tree offset;
4059 tree tmp;
4060 tree stmt;
4061 stmtblock_t block;
4063 gfc_get_backend_locus (&loc);
4064 gfc_set_backend_locus (&sym->declared_at);
4066 /* Descriptor type. */
4067 parm = sym->backend_decl;
4068 type = TREE_TYPE (parm);
4069 gcc_assert (GFC_ARRAY_TYPE_P (type));
4071 gfc_start_block (&block);
4073 if (sym->ts.type == BT_CHARACTER
4074 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4075 gfc_conv_string_length (sym->ts.cl, &block);
4077 /* Evaluate the bounds of the array. */
4078 gfc_trans_array_bounds (type, sym, &offset, &block);
4080 /* Set the offset. */
4081 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4082 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4084 /* Set the pointer itself if we aren't using the parameter directly. */
4085 if (TREE_CODE (parm) != PARM_DECL)
4087 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
4088 gfc_add_modify_expr (&block, parm, tmp);
4090 stmt = gfc_finish_block (&block);
4092 gfc_set_backend_locus (&loc);
4094 gfc_start_block (&block);
4096 /* Add the initialization code to the start of the function. */
4098 if (sym->attr.optional || sym->attr.not_always_present)
4100 tmp = gfc_conv_expr_present (sym);
4101 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4104 gfc_add_expr_to_block (&block, stmt);
4105 gfc_add_expr_to_block (&block, body);
4107 return gfc_finish_block (&block);
4111 /* Modify the descriptor of an array parameter so that it has the
4112 correct lower bound. Also move the upper bound accordingly.
4113 If the array is not packed, it will be copied into a temporary.
4114 For each dimension we set the new lower and upper bounds. Then we copy the
4115 stride and calculate the offset for this dimension. We also work out
4116 what the stride of a packed array would be, and see it the two match.
4117 If the array need repacking, we set the stride to the values we just
4118 calculated, recalculate the offset and copy the array data.
4119 Code is also added to copy the data back at the end of the function.
4122 tree
4123 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
4125 tree size;
4126 tree type;
4127 tree offset;
4128 locus loc;
4129 stmtblock_t block;
4130 stmtblock_t cleanup;
4131 tree lbound;
4132 tree ubound;
4133 tree dubound;
4134 tree dlbound;
4135 tree dumdesc;
4136 tree tmp;
4137 tree stmt;
4138 tree stride, stride2;
4139 tree stmt_packed;
4140 tree stmt_unpacked;
4141 tree partial;
4142 gfc_se se;
4143 int n;
4144 int checkparm;
4145 int no_repack;
4146 bool optional_arg;
4148 /* Do nothing for pointer and allocatable arrays. */
4149 if (sym->attr.pointer || sym->attr.allocatable)
4150 return body;
4152 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
4153 return gfc_trans_g77_array (sym, body);
4155 gfc_get_backend_locus (&loc);
4156 gfc_set_backend_locus (&sym->declared_at);
4158 /* Descriptor type. */
4159 type = TREE_TYPE (tmpdesc);
4160 gcc_assert (GFC_ARRAY_TYPE_P (type));
4161 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4162 dumdesc = build_fold_indirect_ref (dumdesc);
4163 gfc_start_block (&block);
4165 if (sym->ts.type == BT_CHARACTER
4166 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4167 gfc_conv_string_length (sym->ts.cl, &block);
4169 checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);
4171 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
4172 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
4174 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
4176 /* For non-constant shape arrays we only check if the first dimension
4177 is contiguous. Repacking higher dimensions wouldn't gain us
4178 anything as we still don't know the array stride. */
4179 partial = gfc_create_var (boolean_type_node, "partial");
4180 TREE_USED (partial) = 1;
4181 tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4182 tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
4183 gfc_add_modify_expr (&block, partial, tmp);
4185 else
4187 partial = NULL_TREE;
4190 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
4191 here, however I think it does the right thing. */
4192 if (no_repack)
4194 /* Set the first stride. */
4195 stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4196 stride = gfc_evaluate_now (stride, &block);
4198 tmp = build2 (EQ_EXPR, boolean_type_node, stride, gfc_index_zero_node);
4199 tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
4200 gfc_index_one_node, stride);
4201 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
4202 gfc_add_modify_expr (&block, stride, tmp);
4204 /* Allow the user to disable array repacking. */
4205 stmt_unpacked = NULL_TREE;
4207 else
4209 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
4210 /* A library call to repack the array if necessary. */
4211 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4212 stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
4214 stride = gfc_index_one_node;
4217 /* This is for the case where the array data is used directly without
4218 calling the repack function. */
4219 if (no_repack || partial != NULL_TREE)
4220 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
4221 else
4222 stmt_packed = NULL_TREE;
4224 /* Assign the data pointer. */
4225 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4227 /* Don't repack unknown shape arrays when the first stride is 1. */
4228 tmp = build3 (COND_EXPR, TREE_TYPE (stmt_packed), partial,
4229 stmt_packed, stmt_unpacked);
4231 else
4232 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
4233 gfc_add_modify_expr (&block, tmpdesc, fold_convert (type, tmp));
4235 offset = gfc_index_zero_node;
4236 size = gfc_index_one_node;
4238 /* Evaluate the bounds of the array. */
4239 for (n = 0; n < sym->as->rank; n++)
4241 if (checkparm || !sym->as->upper[n])
4243 /* Get the bounds of the actual parameter. */
4244 dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
4245 dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
4247 else
4249 dubound = NULL_TREE;
4250 dlbound = NULL_TREE;
4253 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
4254 if (!INTEGER_CST_P (lbound))
4256 gfc_init_se (&se, NULL);
4257 gfc_conv_expr_type (&se, sym->as->lower[n],
4258 gfc_array_index_type);
4259 gfc_add_block_to_block (&block, &se.pre);
4260 gfc_add_modify_expr (&block, lbound, se.expr);
4263 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
4264 /* Set the desired upper bound. */
4265 if (sym->as->upper[n])
4267 /* We know what we want the upper bound to be. */
4268 if (!INTEGER_CST_P (ubound))
4270 gfc_init_se (&se, NULL);
4271 gfc_conv_expr_type (&se, sym->as->upper[n],
4272 gfc_array_index_type);
4273 gfc_add_block_to_block (&block, &se.pre);
4274 gfc_add_modify_expr (&block, ubound, se.expr);
4277 /* Check the sizes match. */
4278 if (checkparm)
4280 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
4281 char * msg;
4283 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4284 ubound, lbound);
4285 stride2 = build2 (MINUS_EXPR, gfc_array_index_type,
4286 dubound, dlbound);
4287 tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
4288 asprintf (&msg, "%s for dimension %d of array '%s'",
4289 gfc_msg_bounds, n+1, sym->name);
4290 gfc_trans_runtime_check (tmp, &block, &loc, msg);
4291 gfc_free (msg);
4294 else
4296 /* For assumed shape arrays move the upper bound by the same amount
4297 as the lower bound. */
4298 tmp = build2 (MINUS_EXPR, gfc_array_index_type, dubound, dlbound);
4299 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound);
4300 gfc_add_modify_expr (&block, ubound, tmp);
4302 /* The offset of this dimension. offset = offset - lbound * stride. */
4303 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, stride);
4304 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
4306 /* The size of this dimension, and the stride of the next. */
4307 if (n + 1 < sym->as->rank)
4309 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
4311 if (no_repack || partial != NULL_TREE)
4313 stmt_unpacked =
4314 gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
4317 /* Figure out the stride if not a known constant. */
4318 if (!INTEGER_CST_P (stride))
4320 if (no_repack)
4321 stmt_packed = NULL_TREE;
4322 else
4324 /* Calculate stride = size * (ubound + 1 - lbound). */
4325 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4326 gfc_index_one_node, lbound);
4327 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4328 ubound, tmp);
4329 size = fold_build2 (MULT_EXPR, gfc_array_index_type,
4330 size, tmp);
4331 stmt_packed = size;
4334 /* Assign the stride. */
4335 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4336 tmp = build3 (COND_EXPR, gfc_array_index_type, partial,
4337 stmt_unpacked, stmt_packed);
4338 else
4339 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
4340 gfc_add_modify_expr (&block, stride, tmp);
4343 else
4345 stride = GFC_TYPE_ARRAY_SIZE (type);
4347 if (stride && !INTEGER_CST_P (stride))
4349 /* Calculate size = stride * (ubound + 1 - lbound). */
4350 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4351 gfc_index_one_node, lbound);
4352 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4353 ubound, tmp);
4354 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4355 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
4356 gfc_add_modify_expr (&block, stride, tmp);
4361 /* Set the offset. */
4362 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4363 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4365 gfc_trans_vla_type_sizes (sym, &block);
4367 stmt = gfc_finish_block (&block);
4369 gfc_start_block (&block);
4371 /* Only do the entry/initialization code if the arg is present. */
4372 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4373 optional_arg = (sym->attr.optional
4374 || (sym->ns->proc_name->attr.entry_master
4375 && sym->attr.dummy));
4376 if (optional_arg)
4378 tmp = gfc_conv_expr_present (sym);
4379 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4381 gfc_add_expr_to_block (&block, stmt);
4383 /* Add the main function body. */
4384 gfc_add_expr_to_block (&block, body);
4386 /* Cleanup code. */
4387 if (!no_repack)
4389 gfc_start_block (&cleanup);
4391 if (sym->attr.intent != INTENT_IN)
4393 /* Copy the data back. */
4394 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
4395 gfc_add_expr_to_block (&cleanup, tmp);
4398 /* Free the temporary. */
4399 tmp = gfc_call_free (tmpdesc);
4400 gfc_add_expr_to_block (&cleanup, tmp);
4402 stmt = gfc_finish_block (&cleanup);
4404 /* Only do the cleanup if the array was repacked. */
4405 tmp = build_fold_indirect_ref (dumdesc);
4406 tmp = gfc_conv_descriptor_data_get (tmp);
4407 tmp = build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
4408 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4410 if (optional_arg)
4412 tmp = gfc_conv_expr_present (sym);
4413 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4415 gfc_add_expr_to_block (&block, stmt);
4417 /* We don't need to free any memory allocated by internal_pack as it will
4418 be freed at the end of the function by pop_context. */
4419 return gfc_finish_block (&block);
4423 /* Calculate the overall offset, including subreferences. */
4424 static void
4425 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
4426 bool subref, gfc_expr *expr)
4428 tree tmp;
4429 tree field;
4430 tree stride;
4431 tree index;
4432 gfc_ref *ref;
4433 gfc_se start;
4434 int n;
4436 /* If offset is NULL and this is not a subreferenced array, there is
4437 nothing to do. */
4438 if (offset == NULL_TREE)
4440 if (subref)
4441 offset = gfc_index_zero_node;
4442 else
4443 return;
4446 tmp = gfc_conv_array_data (desc);
4447 tmp = build_fold_indirect_ref (tmp);
4448 tmp = gfc_build_array_ref (tmp, offset, NULL);
4450 /* Offset the data pointer for pointer assignments from arrays with
4451 subreferences; eg. my_integer => my_type(:)%integer_component. */
4452 if (subref)
4454 /* Go past the array reference. */
4455 for (ref = expr->ref; ref; ref = ref->next)
4456 if (ref->type == REF_ARRAY &&
4457 ref->u.ar.type != AR_ELEMENT)
4459 ref = ref->next;
4460 break;
4463 /* Calculate the offset for each subsequent subreference. */
4464 for (; ref; ref = ref->next)
4466 switch (ref->type)
4468 case REF_COMPONENT:
4469 field = ref->u.c.component->backend_decl;
4470 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
4471 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
4472 break;
4474 case REF_SUBSTRING:
4475 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
4476 gfc_init_se (&start, NULL);
4477 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
4478 gfc_add_block_to_block (block, &start.pre);
4479 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
4480 break;
4482 case REF_ARRAY:
4483 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
4484 && ref->u.ar.type == AR_ELEMENT);
4486 /* TODO - Add bounds checking. */
4487 stride = gfc_index_one_node;
4488 index = gfc_index_zero_node;
4489 for (n = 0; n < ref->u.ar.dimen; n++)
4491 tree itmp;
4492 tree jtmp;
4494 /* Update the index. */
4495 gfc_init_se (&start, NULL);
4496 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
4497 itmp = gfc_evaluate_now (start.expr, block);
4498 gfc_init_se (&start, NULL);
4499 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
4500 jtmp = gfc_evaluate_now (start.expr, block);
4501 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, itmp, jtmp);
4502 itmp = fold_build2 (MULT_EXPR, gfc_array_index_type, itmp, stride);
4503 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, itmp, index);
4504 index = gfc_evaluate_now (index, block);
4506 /* Update the stride. */
4507 gfc_init_se (&start, NULL);
4508 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
4509 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, start.expr, jtmp);
4510 itmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4511 gfc_index_one_node, itmp);
4512 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, itmp);
4513 stride = gfc_evaluate_now (stride, block);
4516 /* Apply the index to obtain the array element. */
4517 tmp = gfc_build_array_ref (tmp, index, NULL);
4518 break;
4520 default:
4521 gcc_unreachable ();
4522 break;
4527 /* Set the target data pointer. */
4528 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
4529 gfc_conv_descriptor_data_set (block, parm, offset);
4533 /* gfc_conv_expr_descriptor needs the character length of elemental
4534 functions before the function is called so that the size of the
4535 temporary can be obtained. The only way to do this is to convert
4536 the expression, mapping onto the actual arguments. */
4537 static void
4538 get_elemental_fcn_charlen (gfc_expr *expr, gfc_se *se)
4540 gfc_interface_mapping mapping;
4541 gfc_formal_arglist *formal;
4542 gfc_actual_arglist *arg;
4543 gfc_se tse;
4545 formal = expr->symtree->n.sym->formal;
4546 arg = expr->value.function.actual;
4547 gfc_init_interface_mapping (&mapping);
4549 /* Set se = NULL in the calls to the interface mapping, to supress any
4550 backend stuff. */
4551 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
4553 if (!arg->expr)
4554 continue;
4555 if (formal->sym)
4556 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
4559 gfc_init_se (&tse, NULL);
4561 /* Build the expression for the character length and convert it. */
4562 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.cl->length);
4564 gfc_add_block_to_block (&se->pre, &tse.pre);
4565 gfc_add_block_to_block (&se->post, &tse.post);
4566 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
4567 tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
4568 build_int_cst (gfc_charlen_type_node, 0));
4569 expr->ts.cl->backend_decl = tse.expr;
4570 gfc_free_interface_mapping (&mapping);
4574 /* Convert an array for passing as an actual argument. Expressions and
4575 vector subscripts are evaluated and stored in a temporary, which is then
4576 passed. For whole arrays the descriptor is passed. For array sections
4577 a modified copy of the descriptor is passed, but using the original data.
4579 This function is also used for array pointer assignments, and there
4580 are three cases:
4582 - se->want_pointer && !se->direct_byref
4583 EXPR is an actual argument. On exit, se->expr contains a
4584 pointer to the array descriptor.
4586 - !se->want_pointer && !se->direct_byref
4587 EXPR is an actual argument to an intrinsic function or the
4588 left-hand side of a pointer assignment. On exit, se->expr
4589 contains the descriptor for EXPR.
4591 - !se->want_pointer && se->direct_byref
4592 EXPR is the right-hand side of a pointer assignment and
4593 se->expr is the descriptor for the previously-evaluated
4594 left-hand side. The function creates an assignment from
4595 EXPR to se->expr. */
4597 void
4598 gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
4600 gfc_loopinfo loop;
4601 gfc_ss *secss;
4602 gfc_ss_info *info;
4603 int need_tmp;
4604 int n;
4605 tree tmp;
4606 tree desc;
4607 stmtblock_t block;
4608 tree start;
4609 tree offset;
4610 int full;
4611 bool subref_array_target = false;
4613 gcc_assert (ss != gfc_ss_terminator);
4615 /* Special case things we know we can pass easily. */
4616 switch (expr->expr_type)
4618 case EXPR_VARIABLE:
4619 /* If we have a linear array section, we can pass it directly.
4620 Otherwise we need to copy it into a temporary. */
4622 /* Find the SS for the array section. */
4623 secss = ss;
4624 while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
4625 secss = secss->next;
4627 gcc_assert (secss != gfc_ss_terminator);
4628 info = &secss->data.info;
4630 /* Get the descriptor for the array. */
4631 gfc_conv_ss_descriptor (&se->pre, secss, 0);
4632 desc = info->descriptor;
4634 subref_array_target = se->direct_byref && is_subref_array (expr);
4635 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
4636 && !subref_array_target;
4638 if (need_tmp)
4639 full = 0;
4640 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4642 /* Create a new descriptor if the array doesn't have one. */
4643 full = 0;
4645 else if (info->ref->u.ar.type == AR_FULL)
4646 full = 1;
4647 else if (se->direct_byref)
4648 full = 0;
4649 else
4650 full = gfc_full_array_ref_p (info->ref);
4652 if (full)
4654 if (se->direct_byref)
4656 /* Copy the descriptor for pointer assignments. */
4657 gfc_add_modify_expr (&se->pre, se->expr, desc);
4659 /* Add any offsets from subreferences. */
4660 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
4661 subref_array_target, expr);
4663 else if (se->want_pointer)
4665 /* We pass full arrays directly. This means that pointers and
4666 allocatable arrays should also work. */
4667 se->expr = build_fold_addr_expr (desc);
4669 else
4671 se->expr = desc;
4674 if (expr->ts.type == BT_CHARACTER)
4675 se->string_length = gfc_get_expr_charlen (expr);
4677 return;
4679 break;
4681 case EXPR_FUNCTION:
4682 /* A transformational function return value will be a temporary
4683 array descriptor. We still need to go through the scalarizer
4684 to create the descriptor. Elemental functions ar handled as
4685 arbitrary expressions, i.e. copy to a temporary. */
4686 secss = ss;
4687 /* Look for the SS for this function. */
4688 while (secss != gfc_ss_terminator
4689 && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
4690 secss = secss->next;
4692 if (se->direct_byref)
4694 gcc_assert (secss != gfc_ss_terminator);
4696 /* For pointer assignments pass the descriptor directly. */
4697 se->ss = secss;
4698 se->expr = build_fold_addr_expr (se->expr);
4699 gfc_conv_expr (se, expr);
4700 return;
4703 if (secss == gfc_ss_terminator)
4705 /* Elemental function. */
4706 need_tmp = 1;
4707 if (expr->ts.type == BT_CHARACTER
4708 && expr->ts.cl->length->expr_type != EXPR_CONSTANT)
4709 get_elemental_fcn_charlen (expr, se);
4711 info = NULL;
4713 else
4715 /* Transformational function. */
4716 info = &secss->data.info;
4717 need_tmp = 0;
4719 break;
4721 case EXPR_ARRAY:
4722 /* Constant array constructors don't need a temporary. */
4723 if (ss->type == GFC_SS_CONSTRUCTOR
4724 && expr->ts.type != BT_CHARACTER
4725 && gfc_constant_array_constructor_p (expr->value.constructor))
4727 need_tmp = 0;
4728 info = &ss->data.info;
4729 secss = ss;
4731 else
4733 need_tmp = 1;
4734 secss = NULL;
4735 info = NULL;
4737 break;
4739 default:
4740 /* Something complicated. Copy it into a temporary. */
4741 need_tmp = 1;
4742 secss = NULL;
4743 info = NULL;
4744 break;
4748 gfc_init_loopinfo (&loop);
4750 /* Associate the SS with the loop. */
4751 gfc_add_ss_to_loop (&loop, ss);
4753 /* Tell the scalarizer not to bother creating loop variables, etc. */
4754 if (!need_tmp)
4755 loop.array_parameter = 1;
4756 else
4757 /* The right-hand side of a pointer assignment mustn't use a temporary. */
4758 gcc_assert (!se->direct_byref);
4760 /* Setup the scalarizing loops and bounds. */
4761 gfc_conv_ss_startstride (&loop);
4763 if (need_tmp)
4765 /* Tell the scalarizer to make a temporary. */
4766 loop.temp_ss = gfc_get_ss ();
4767 loop.temp_ss->type = GFC_SS_TEMP;
4768 loop.temp_ss->next = gfc_ss_terminator;
4770 if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl)
4771 gfc_conv_string_length (expr->ts.cl, &se->pre);
4773 loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
4775 if (expr->ts.type == BT_CHARACTER)
4776 loop.temp_ss->string_length = expr->ts.cl->backend_decl;
4777 else
4778 loop.temp_ss->string_length = NULL;
4780 se->string_length = loop.temp_ss->string_length;
4781 loop.temp_ss->data.temp.dimen = loop.dimen;
4782 gfc_add_ss_to_loop (&loop, loop.temp_ss);
4785 gfc_conv_loop_setup (&loop);
4787 if (need_tmp)
4789 /* Copy into a temporary and pass that. We don't need to copy the data
4790 back because expressions and vector subscripts must be INTENT_IN. */
4791 /* TODO: Optimize passing function return values. */
4792 gfc_se lse;
4793 gfc_se rse;
4795 /* Start the copying loops. */
4796 gfc_mark_ss_chain_used (loop.temp_ss, 1);
4797 gfc_mark_ss_chain_used (ss, 1);
4798 gfc_start_scalarized_body (&loop, &block);
4800 /* Copy each data element. */
4801 gfc_init_se (&lse, NULL);
4802 gfc_copy_loopinfo_to_se (&lse, &loop);
4803 gfc_init_se (&rse, NULL);
4804 gfc_copy_loopinfo_to_se (&rse, &loop);
4806 lse.ss = loop.temp_ss;
4807 rse.ss = ss;
4809 gfc_conv_scalarized_array_ref (&lse, NULL);
4810 if (expr->ts.type == BT_CHARACTER)
4812 gfc_conv_expr (&rse, expr);
4813 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
4814 rse.expr = build_fold_indirect_ref (rse.expr);
4816 else
4817 gfc_conv_expr_val (&rse, expr);
4819 gfc_add_block_to_block (&block, &rse.pre);
4820 gfc_add_block_to_block (&block, &lse.pre);
4822 lse.string_length = rse.string_length;
4823 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
4824 expr->expr_type == EXPR_VARIABLE);
4825 gfc_add_expr_to_block (&block, tmp);
4827 /* Finish the copying loops. */
4828 gfc_trans_scalarizing_loops (&loop, &block);
4830 desc = loop.temp_ss->data.info.descriptor;
4832 gcc_assert (is_gimple_lvalue (desc));
4834 else if (expr->expr_type == EXPR_FUNCTION)
4836 desc = info->descriptor;
4837 se->string_length = ss->string_length;
4839 else
4841 /* We pass sections without copying to a temporary. Make a new
4842 descriptor and point it at the section we want. The loop variable
4843 limits will be the limits of the section.
4844 A function may decide to repack the array to speed up access, but
4845 we're not bothered about that here. */
4846 int dim, ndim;
4847 tree parm;
4848 tree parmtype;
4849 tree stride;
4850 tree from;
4851 tree to;
4852 tree base;
4854 /* Set the string_length for a character array. */
4855 if (expr->ts.type == BT_CHARACTER)
4856 se->string_length = gfc_get_expr_charlen (expr);
4858 desc = info->descriptor;
4859 gcc_assert (secss && secss != gfc_ss_terminator);
4860 if (se->direct_byref)
4862 /* For pointer assignments we fill in the destination. */
4863 parm = se->expr;
4864 parmtype = TREE_TYPE (parm);
4866 else
4868 /* Otherwise make a new one. */
4869 parmtype = gfc_get_element_type (TREE_TYPE (desc));
4870 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
4871 loop.from, loop.to, 0,
4872 GFC_ARRAY_UNKNOWN);
4873 parm = gfc_create_var (parmtype, "parm");
4876 offset = gfc_index_zero_node;
4877 dim = 0;
4879 /* The following can be somewhat confusing. We have two
4880 descriptors, a new one and the original array.
4881 {parm, parmtype, dim} refer to the new one.
4882 {desc, type, n, secss, loop} refer to the original, which maybe
4883 a descriptorless array.
4884 The bounds of the scalarization are the bounds of the section.
4885 We don't have to worry about numeric overflows when calculating
4886 the offsets because all elements are within the array data. */
4888 /* Set the dtype. */
4889 tmp = gfc_conv_descriptor_dtype (parm);
4890 gfc_add_modify_expr (&loop.pre, tmp, gfc_get_dtype (parmtype));
4892 /* Set offset for assignments to pointer only to zero if it is not
4893 the full array. */
4894 if (se->direct_byref
4895 && info->ref && info->ref->u.ar.type != AR_FULL)
4896 base = gfc_index_zero_node;
4897 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4898 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
4899 else
4900 base = NULL_TREE;
4902 ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
4903 for (n = 0; n < ndim; n++)
4905 stride = gfc_conv_array_stride (desc, n);
4907 /* Work out the offset. */
4908 if (info->ref
4909 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4911 gcc_assert (info->subscript[n]
4912 && info->subscript[n]->type == GFC_SS_SCALAR);
4913 start = info->subscript[n]->data.scalar.expr;
4915 else
4917 /* Check we haven't somehow got out of sync. */
4918 gcc_assert (info->dim[dim] == n);
4920 /* Evaluate and remember the start of the section. */
4921 start = info->start[dim];
4922 stride = gfc_evaluate_now (stride, &loop.pre);
4925 tmp = gfc_conv_array_lbound (desc, n);
4926 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp);
4928 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
4929 offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
4931 if (info->ref
4932 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4934 /* For elemental dimensions, we only need the offset. */
4935 continue;
4938 /* Vector subscripts need copying and are handled elsewhere. */
4939 if (info->ref)
4940 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
4942 /* Set the new lower bound. */
4943 from = loop.from[dim];
4944 to = loop.to[dim];
4946 /* If we have an array section or are assigning make sure that
4947 the lower bound is 1. References to the full
4948 array should otherwise keep the original bounds. */
4949 if ((!info->ref
4950 || info->ref->u.ar.type != AR_FULL)
4951 && !integer_onep (from))
4953 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4954 gfc_index_one_node, from);
4955 to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
4956 from = gfc_index_one_node;
4958 tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
4959 gfc_add_modify_expr (&loop.pre, tmp, from);
4961 /* Set the new upper bound. */
4962 tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
4963 gfc_add_modify_expr (&loop.pre, tmp, to);
4965 /* Multiply the stride by the section stride to get the
4966 total stride. */
4967 stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
4968 stride, info->stride[dim]);
4970 if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
4972 base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
4973 base, stride);
4975 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4977 tmp = gfc_conv_array_lbound (desc, n);
4978 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
4979 tmp, loop.from[dim]);
4980 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base),
4981 tmp, gfc_conv_array_stride (desc, n));
4982 base = fold_build2 (PLUS_EXPR, TREE_TYPE (base),
4983 tmp, base);
4986 /* Store the new stride. */
4987 tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
4988 gfc_add_modify_expr (&loop.pre, tmp, stride);
4990 dim++;
4993 if (se->data_not_needed)
4994 gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
4995 else
4996 /* Point the data pointer at the first element in the section. */
4997 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
4998 subref_array_target, expr);
5000 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5001 && !se->data_not_needed)
5003 /* Set the offset. */
5004 tmp = gfc_conv_descriptor_offset (parm);
5005 gfc_add_modify_expr (&loop.pre, tmp, base);
5007 else
5009 /* Only the callee knows what the correct offset it, so just set
5010 it to zero here. */
5011 tmp = gfc_conv_descriptor_offset (parm);
5012 gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
5014 desc = parm;
5017 if (!se->direct_byref)
5019 /* Get a pointer to the new descriptor. */
5020 if (se->want_pointer)
5021 se->expr = build_fold_addr_expr (desc);
5022 else
5023 se->expr = desc;
5026 gfc_add_block_to_block (&se->pre, &loop.pre);
5027 gfc_add_block_to_block (&se->post, &loop.post);
5029 /* Cleanup the scalarizer. */
5030 gfc_cleanup_loop (&loop);
5034 /* Convert an array for passing as an actual parameter. */
5035 /* TODO: Optimize passing g77 arrays. */
5037 void
5038 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
5040 tree ptr;
5041 tree desc;
5042 tree tmp = NULL_TREE;
5043 tree stmt;
5044 tree parent = DECL_CONTEXT (current_function_decl);
5045 bool full_array_var, this_array_result;
5046 gfc_symbol *sym;
5047 stmtblock_t block;
5049 full_array_var = (expr->expr_type == EXPR_VARIABLE
5050 && expr->ref->u.ar.type == AR_FULL);
5051 sym = full_array_var ? expr->symtree->n.sym : NULL;
5053 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
5055 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
5056 expr->ts.cl->backend_decl = tmp;
5057 se->string_length = tmp;
5060 /* Is this the result of the enclosing procedure? */
5061 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
5062 if (this_array_result
5063 && (sym->backend_decl != current_function_decl)
5064 && (sym->backend_decl != parent))
5065 this_array_result = false;
5067 /* Passing address of the array if it is not pointer or assumed-shape. */
5068 if (full_array_var && g77 && !this_array_result)
5070 tmp = gfc_get_symbol_decl (sym);
5072 if (sym->ts.type == BT_CHARACTER)
5073 se->string_length = sym->ts.cl->backend_decl;
5074 if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE
5075 && !sym->attr.allocatable)
5077 /* Some variables are declared directly, others are declared as
5078 pointers and allocated on the heap. */
5079 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
5080 se->expr = tmp;
5081 else
5082 se->expr = build_fold_addr_expr (tmp);
5083 return;
5085 if (sym->attr.allocatable)
5087 if (sym->attr.dummy || sym->attr.result)
5089 gfc_conv_expr_descriptor (se, expr, ss);
5090 se->expr = gfc_conv_array_data (se->expr);
5092 else
5093 se->expr = gfc_conv_array_data (tmp);
5094 return;
5098 if (this_array_result)
5100 /* Result of the enclosing function. */
5101 gfc_conv_expr_descriptor (se, expr, ss);
5102 se->expr = build_fold_addr_expr (se->expr);
5104 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
5105 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
5106 se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
5108 return;
5110 else
5112 /* Every other type of array. */
5113 se->want_pointer = 1;
5114 gfc_conv_expr_descriptor (se, expr, ss);
5118 /* Deallocate the allocatable components of structures that are
5119 not variable. */
5120 if (expr->ts.type == BT_DERIVED
5121 && expr->ts.derived->attr.alloc_comp
5122 && expr->expr_type != EXPR_VARIABLE)
5124 tmp = build_fold_indirect_ref (se->expr);
5125 tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
5126 gfc_add_expr_to_block (&se->post, tmp);
5129 if (g77)
5131 desc = se->expr;
5132 /* Repack the array. */
5133 ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
5134 ptr = gfc_evaluate_now (ptr, &se->pre);
5135 se->expr = ptr;
5137 gfc_start_block (&block);
5139 /* Copy the data back. */
5140 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
5141 gfc_add_expr_to_block (&block, tmp);
5143 /* Free the temporary. */
5144 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
5145 gfc_add_expr_to_block (&block, tmp);
5147 stmt = gfc_finish_block (&block);
5149 gfc_init_block (&block);
5150 /* Only if it was repacked. This code needs to be executed before the
5151 loop cleanup code. */
5152 tmp = build_fold_indirect_ref (desc);
5153 tmp = gfc_conv_array_data (tmp);
5154 tmp = build2 (NE_EXPR, boolean_type_node,
5155 fold_convert (TREE_TYPE (tmp), ptr), tmp);
5156 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
5158 gfc_add_expr_to_block (&block, tmp);
5159 gfc_add_block_to_block (&block, &se->post);
5161 gfc_init_block (&se->post);
5162 gfc_add_block_to_block (&se->post, &block);
5167 /* Generate code to deallocate an array, if it is allocated. */
5169 tree
5170 gfc_trans_dealloc_allocated (tree descriptor)
5172 tree tmp;
5173 tree var;
5174 stmtblock_t block;
5176 gfc_start_block (&block);
5178 var = gfc_conv_descriptor_data_get (descriptor);
5179 STRIP_NOPS (var);
5181 /* Call array_deallocate with an int * present in the second argument.
5182 Although it is ignored here, it's presence ensures that arrays that
5183 are already deallocated are ignored. */
5184 tmp = gfc_deallocate_with_status (var, NULL_TREE, true);
5185 gfc_add_expr_to_block (&block, tmp);
5187 /* Zero the data pointer. */
5188 tmp = build2 (MODIFY_EXPR, void_type_node,
5189 var, build_int_cst (TREE_TYPE (var), 0));
5190 gfc_add_expr_to_block (&block, tmp);
5192 return gfc_finish_block (&block);
5196 /* This helper function calculates the size in words of a full array. */
5198 static tree
5199 get_full_array_size (stmtblock_t *block, tree decl, int rank)
5201 tree idx;
5202 tree nelems;
5203 tree tmp;
5204 idx = gfc_rank_cst[rank - 1];
5205 nelems = gfc_conv_descriptor_ubound (decl, idx);
5206 tmp = gfc_conv_descriptor_lbound (decl, idx);
5207 tmp = build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
5208 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
5209 tmp, gfc_index_one_node);
5210 tmp = gfc_evaluate_now (tmp, block);
5212 nelems = gfc_conv_descriptor_stride (decl, idx);
5213 tmp = build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
5214 return gfc_evaluate_now (tmp, block);
5218 /* Allocate dest to the same size as src, and copy src -> dest. */
5220 tree
5221 gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
5223 tree tmp;
5224 tree size;
5225 tree nelems;
5226 tree null_cond;
5227 tree null_data;
5228 stmtblock_t block;
5230 /* If the source is null, set the destination to null. */
5231 gfc_init_block (&block);
5232 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
5233 null_data = gfc_finish_block (&block);
5235 gfc_init_block (&block);
5237 nelems = get_full_array_size (&block, src, rank);
5238 size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
5239 fold_convert (gfc_array_index_type,
5240 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
5242 /* Allocate memory to the destination. */
5243 tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
5244 size);
5245 gfc_conv_descriptor_data_set (&block, dest, tmp);
5247 /* We know the temporary and the value will be the same length,
5248 so can use memcpy. */
5249 tmp = built_in_decls[BUILT_IN_MEMCPY];
5250 tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
5251 gfc_conv_descriptor_data_get (src), size);
5252 gfc_add_expr_to_block (&block, tmp);
5253 tmp = gfc_finish_block (&block);
5255 /* Null the destination if the source is null; otherwise do
5256 the allocate and copy. */
5257 null_cond = gfc_conv_descriptor_data_get (src);
5258 null_cond = convert (pvoid_type_node, null_cond);
5259 null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
5260 null_pointer_node);
5261 return build3_v (COND_EXPR, null_cond, tmp, null_data);
5265 /* Recursively traverse an object of derived type, generating code to
5266 deallocate, nullify or copy allocatable components. This is the work horse
5267 function for the functions named in this enum. */
5269 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
5271 static tree
5272 structure_alloc_comps (gfc_symbol * der_type, tree decl,
5273 tree dest, int rank, int purpose)
5275 gfc_component *c;
5276 gfc_loopinfo loop;
5277 stmtblock_t fnblock;
5278 stmtblock_t loopbody;
5279 tree tmp;
5280 tree comp;
5281 tree dcmp;
5282 tree nelems;
5283 tree index;
5284 tree var;
5285 tree cdecl;
5286 tree ctype;
5287 tree vref, dref;
5288 tree null_cond = NULL_TREE;
5290 gfc_init_block (&fnblock);
5292 if (POINTER_TYPE_P (TREE_TYPE (decl)))
5293 decl = build_fold_indirect_ref (decl);
5295 /* If this an array of derived types with allocatable components
5296 build a loop and recursively call this function. */
5297 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
5298 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5300 tmp = gfc_conv_array_data (decl);
5301 var = build_fold_indirect_ref (tmp);
5303 /* Get the number of elements - 1 and set the counter. */
5304 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5306 /* Use the descriptor for an allocatable array. Since this
5307 is a full array reference, we only need the descriptor
5308 information from dimension = rank. */
5309 tmp = get_full_array_size (&fnblock, decl, rank);
5310 tmp = build2 (MINUS_EXPR, gfc_array_index_type,
5311 tmp, gfc_index_one_node);
5313 null_cond = gfc_conv_descriptor_data_get (decl);
5314 null_cond = build2 (NE_EXPR, boolean_type_node, null_cond,
5315 build_int_cst (TREE_TYPE (null_cond), 0));
5317 else
5319 /* Otherwise use the TYPE_DOMAIN information. */
5320 tmp = array_type_nelts (TREE_TYPE (decl));
5321 tmp = fold_convert (gfc_array_index_type, tmp);
5324 /* Remember that this is, in fact, the no. of elements - 1. */
5325 nelems = gfc_evaluate_now (tmp, &fnblock);
5326 index = gfc_create_var (gfc_array_index_type, "S");
5328 /* Build the body of the loop. */
5329 gfc_init_block (&loopbody);
5331 vref = gfc_build_array_ref (var, index, NULL);
5333 if (purpose == COPY_ALLOC_COMP)
5335 tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
5336 gfc_add_expr_to_block (&fnblock, tmp);
5338 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (dest));
5339 dref = gfc_build_array_ref (tmp, index, NULL);
5340 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
5342 else
5343 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
5345 gfc_add_expr_to_block (&loopbody, tmp);
5347 /* Build the loop and return. */
5348 gfc_init_loopinfo (&loop);
5349 loop.dimen = 1;
5350 loop.from[0] = gfc_index_zero_node;
5351 loop.loopvar[0] = index;
5352 loop.to[0] = nelems;
5353 gfc_trans_scalarizing_loops (&loop, &loopbody);
5354 gfc_add_block_to_block (&fnblock, &loop.pre);
5356 tmp = gfc_finish_block (&fnblock);
5357 if (null_cond != NULL_TREE)
5358 tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
5360 return tmp;
5363 /* Otherwise, act on the components or recursively call self to
5364 act on a chain of components. */
5365 for (c = der_type->components; c; c = c->next)
5367 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
5368 && c->ts.derived->attr.alloc_comp;
5369 cdecl = c->backend_decl;
5370 ctype = TREE_TYPE (cdecl);
5372 switch (purpose)
5374 case DEALLOCATE_ALLOC_COMP:
5375 /* Do not deallocate the components of ultimate pointer
5376 components. */
5377 if (cmp_has_alloc_comps && !c->pointer)
5379 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5380 rank = c->as ? c->as->rank : 0;
5381 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5382 rank, purpose);
5383 gfc_add_expr_to_block (&fnblock, tmp);
5386 if (c->allocatable)
5388 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5389 tmp = gfc_trans_dealloc_allocated (comp);
5390 gfc_add_expr_to_block (&fnblock, tmp);
5392 break;
5394 case NULLIFY_ALLOC_COMP:
5395 if (c->pointer)
5396 continue;
5397 else if (c->allocatable)
5399 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5400 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
5402 else if (cmp_has_alloc_comps)
5404 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5405 rank = c->as ? c->as->rank : 0;
5406 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5407 rank, purpose);
5408 gfc_add_expr_to_block (&fnblock, tmp);
5410 break;
5412 case COPY_ALLOC_COMP:
5413 if (c->pointer)
5414 continue;
5416 /* We need source and destination components. */
5417 comp = build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5418 dcmp = build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
5419 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
5421 if (c->allocatable && !cmp_has_alloc_comps)
5423 tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
5424 gfc_add_expr_to_block (&fnblock, tmp);
5427 if (cmp_has_alloc_comps)
5429 rank = c->as ? c->as->rank : 0;
5430 tmp = fold_convert (TREE_TYPE (dcmp), comp);
5431 gfc_add_modify_expr (&fnblock, dcmp, tmp);
5432 tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
5433 rank, purpose);
5434 gfc_add_expr_to_block (&fnblock, tmp);
5436 break;
5438 default:
5439 gcc_unreachable ();
5440 break;
5444 return gfc_finish_block (&fnblock);
5447 /* Recursively traverse an object of derived type, generating code to
5448 nullify allocatable components. */
5450 tree
5451 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5453 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5454 NULLIFY_ALLOC_COMP);
5458 /* Recursively traverse an object of derived type, generating code to
5459 deallocate allocatable components. */
5461 tree
5462 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5464 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5465 DEALLOCATE_ALLOC_COMP);
5469 /* Recursively traverse an object of derived type, generating code to
5470 copy its allocatable components. */
5472 tree
5473 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
5475 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
5479 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
5480 Do likewise, recursively if necessary, with the allocatable components of
5481 derived types. */
5483 tree
5484 gfc_trans_deferred_array (gfc_symbol * sym, tree body)
5486 tree type;
5487 tree tmp;
5488 tree descriptor;
5489 stmtblock_t fnblock;
5490 locus loc;
5491 int rank;
5492 bool sym_has_alloc_comp;
5494 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
5495 && sym->ts.derived->attr.alloc_comp;
5497 /* Make sure the frontend gets these right. */
5498 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
5499 fatal_error ("Possible frontend bug: Deferred array size without pointer, "
5500 "allocatable attribute or derived type without allocatable "
5501 "components.");
5503 gfc_init_block (&fnblock);
5505 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
5506 || TREE_CODE (sym->backend_decl) == PARM_DECL);
5508 if (sym->ts.type == BT_CHARACTER
5509 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
5511 gfc_conv_string_length (sym->ts.cl, &fnblock);
5512 gfc_trans_vla_type_sizes (sym, &fnblock);
5515 /* Dummy and use associated variables don't need anything special. */
5516 if (sym->attr.dummy || sym->attr.use_assoc)
5518 gfc_add_expr_to_block (&fnblock, body);
5520 return gfc_finish_block (&fnblock);
5523 gfc_get_backend_locus (&loc);
5524 gfc_set_backend_locus (&sym->declared_at);
5525 descriptor = sym->backend_decl;
5527 /* Although static, derived types with default initializers and
5528 allocatable components must not be nulled wholesale; instead they
5529 are treated component by component. */
5530 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
5532 /* SAVEd variables are not freed on exit. */
5533 gfc_trans_static_array_pointer (sym);
5534 return body;
5537 /* Get the descriptor type. */
5538 type = TREE_TYPE (sym->backend_decl);
5540 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
5542 if (!sym->attr.save)
5544 rank = sym->as ? sym->as->rank : 0;
5545 tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
5546 gfc_add_expr_to_block (&fnblock, tmp);
5549 else if (!GFC_DESCRIPTOR_TYPE_P (type))
5551 /* If the backend_decl is not a descriptor, we must have a pointer
5552 to one. */
5553 descriptor = build_fold_indirect_ref (sym->backend_decl);
5554 type = TREE_TYPE (descriptor);
5557 /* NULLIFY the data pointer. */
5558 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
5559 gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
5561 gfc_add_expr_to_block (&fnblock, body);
5563 gfc_set_backend_locus (&loc);
5565 /* Allocatable arrays need to be freed when they go out of scope.
5566 The allocatable components of pointers must not be touched. */
5567 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
5568 && !sym->attr.pointer && !sym->attr.save)
5570 int rank;
5571 rank = sym->as ? sym->as->rank : 0;
5572 tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
5573 gfc_add_expr_to_block (&fnblock, tmp);
5576 if (sym->attr.allocatable && !sym->attr.save)
5578 tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
5579 gfc_add_expr_to_block (&fnblock, tmp);
5582 return gfc_finish_block (&fnblock);
5585 /************ Expression Walking Functions ******************/
5587 /* Walk a variable reference.
5589 Possible extension - multiple component subscripts.
5590 x(:,:) = foo%a(:)%b(:)
5591 Transforms to
5592 forall (i=..., j=...)
5593 x(i,j) = foo%a(j)%b(i)
5594 end forall
5595 This adds a fair amount of complexity because you need to deal with more
5596 than one ref. Maybe handle in a similar manner to vector subscripts.
5597 Maybe not worth the effort. */
5600 static gfc_ss *
5601 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
5603 gfc_ref *ref;
5604 gfc_array_ref *ar;
5605 gfc_ss *newss;
5606 gfc_ss *head;
5607 int n;
5609 for (ref = expr->ref; ref; ref = ref->next)
5610 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
5611 break;
5613 for (; ref; ref = ref->next)
5615 if (ref->type == REF_SUBSTRING)
5617 newss = gfc_get_ss ();
5618 newss->type = GFC_SS_SCALAR;
5619 newss->expr = ref->u.ss.start;
5620 newss->next = ss;
5621 ss = newss;
5623 newss = gfc_get_ss ();
5624 newss->type = GFC_SS_SCALAR;
5625 newss->expr = ref->u.ss.end;
5626 newss->next = ss;
5627 ss = newss;
5630 /* We're only interested in array sections from now on. */
5631 if (ref->type != REF_ARRAY)
5632 continue;
5634 ar = &ref->u.ar;
5635 switch (ar->type)
5637 case AR_ELEMENT:
5638 for (n = 0; n < ar->dimen; n++)
5640 newss = gfc_get_ss ();
5641 newss->type = GFC_SS_SCALAR;
5642 newss->expr = ar->start[n];
5643 newss->next = ss;
5644 ss = newss;
5646 break;
5648 case AR_FULL:
5649 newss = gfc_get_ss ();
5650 newss->type = GFC_SS_SECTION;
5651 newss->expr = expr;
5652 newss->next = ss;
5653 newss->data.info.dimen = ar->as->rank;
5654 newss->data.info.ref = ref;
5656 /* Make sure array is the same as array(:,:), this way
5657 we don't need to special case all the time. */
5658 ar->dimen = ar->as->rank;
5659 for (n = 0; n < ar->dimen; n++)
5661 newss->data.info.dim[n] = n;
5662 ar->dimen_type[n] = DIMEN_RANGE;
5664 gcc_assert (ar->start[n] == NULL);
5665 gcc_assert (ar->end[n] == NULL);
5666 gcc_assert (ar->stride[n] == NULL);
5668 ss = newss;
5669 break;
5671 case AR_SECTION:
5672 newss = gfc_get_ss ();
5673 newss->type = GFC_SS_SECTION;
5674 newss->expr = expr;
5675 newss->next = ss;
5676 newss->data.info.dimen = 0;
5677 newss->data.info.ref = ref;
5679 head = newss;
5681 /* We add SS chains for all the subscripts in the section. */
5682 for (n = 0; n < ar->dimen; n++)
5684 gfc_ss *indexss;
5686 switch (ar->dimen_type[n])
5688 case DIMEN_ELEMENT:
5689 /* Add SS for elemental (scalar) subscripts. */
5690 gcc_assert (ar->start[n]);
5691 indexss = gfc_get_ss ();
5692 indexss->type = GFC_SS_SCALAR;
5693 indexss->expr = ar->start[n];
5694 indexss->next = gfc_ss_terminator;
5695 indexss->loop_chain = gfc_ss_terminator;
5696 newss->data.info.subscript[n] = indexss;
5697 break;
5699 case DIMEN_RANGE:
5700 /* We don't add anything for sections, just remember this
5701 dimension for later. */
5702 newss->data.info.dim[newss->data.info.dimen] = n;
5703 newss->data.info.dimen++;
5704 break;
5706 case DIMEN_VECTOR:
5707 /* Create a GFC_SS_VECTOR index in which we can store
5708 the vector's descriptor. */
5709 indexss = gfc_get_ss ();
5710 indexss->type = GFC_SS_VECTOR;
5711 indexss->expr = ar->start[n];
5712 indexss->next = gfc_ss_terminator;
5713 indexss->loop_chain = gfc_ss_terminator;
5714 newss->data.info.subscript[n] = indexss;
5715 newss->data.info.dim[newss->data.info.dimen] = n;
5716 newss->data.info.dimen++;
5717 break;
5719 default:
5720 /* We should know what sort of section it is by now. */
5721 gcc_unreachable ();
5724 /* We should have at least one non-elemental dimension. */
5725 gcc_assert (newss->data.info.dimen > 0);
5726 ss = newss;
5727 break;
5729 default:
5730 /* We should know what sort of section it is by now. */
5731 gcc_unreachable ();
5735 return ss;
5739 /* Walk an expression operator. If only one operand of a binary expression is
5740 scalar, we must also add the scalar term to the SS chain. */
5742 static gfc_ss *
5743 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
5745 gfc_ss *head;
5746 gfc_ss *head2;
5747 gfc_ss *newss;
5749 head = gfc_walk_subexpr (ss, expr->value.op.op1);
5750 if (expr->value.op.op2 == NULL)
5751 head2 = head;
5752 else
5753 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
5755 /* All operands are scalar. Pass back and let the caller deal with it. */
5756 if (head2 == ss)
5757 return head2;
5759 /* All operands require scalarization. */
5760 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
5761 return head2;
5763 /* One of the operands needs scalarization, the other is scalar.
5764 Create a gfc_ss for the scalar expression. */
5765 newss = gfc_get_ss ();
5766 newss->type = GFC_SS_SCALAR;
5767 if (head == ss)
5769 /* First operand is scalar. We build the chain in reverse order, so
5770 add the scarar SS after the second operand. */
5771 head = head2;
5772 while (head && head->next != ss)
5773 head = head->next;
5774 /* Check we haven't somehow broken the chain. */
5775 gcc_assert (head);
5776 newss->next = ss;
5777 head->next = newss;
5778 newss->expr = expr->value.op.op1;
5780 else /* head2 == head */
5782 gcc_assert (head2 == head);
5783 /* Second operand is scalar. */
5784 newss->next = head2;
5785 head2 = newss;
5786 newss->expr = expr->value.op.op2;
5789 return head2;
5793 /* Reverse a SS chain. */
5795 gfc_ss *
5796 gfc_reverse_ss (gfc_ss * ss)
5798 gfc_ss *next;
5799 gfc_ss *head;
5801 gcc_assert (ss != NULL);
5803 head = gfc_ss_terminator;
5804 while (ss != gfc_ss_terminator)
5806 next = ss->next;
5807 /* Check we didn't somehow break the chain. */
5808 gcc_assert (next != NULL);
5809 ss->next = head;
5810 head = ss;
5811 ss = next;
5814 return (head);
5818 /* Walk the arguments of an elemental function. */
5820 gfc_ss *
5821 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
5822 gfc_ss_type type)
5824 int scalar;
5825 gfc_ss *head;
5826 gfc_ss *tail;
5827 gfc_ss *newss;
5829 head = gfc_ss_terminator;
5830 tail = NULL;
5831 scalar = 1;
5832 for (; arg; arg = arg->next)
5834 if (!arg->expr)
5835 continue;
5837 newss = gfc_walk_subexpr (head, arg->expr);
5838 if (newss == head)
5840 /* Scalar argument. */
5841 newss = gfc_get_ss ();
5842 newss->type = type;
5843 newss->expr = arg->expr;
5844 newss->next = head;
5846 else
5847 scalar = 0;
5849 head = newss;
5850 if (!tail)
5852 tail = head;
5853 while (tail->next != gfc_ss_terminator)
5854 tail = tail->next;
5858 if (scalar)
5860 /* If all the arguments are scalar we don't need the argument SS. */
5861 gfc_free_ss_chain (head);
5862 /* Pass it back. */
5863 return ss;
5866 /* Add it onto the existing chain. */
5867 tail->next = ss;
5868 return head;
5872 /* Walk a function call. Scalar functions are passed back, and taken out of
5873 scalarization loops. For elemental functions we walk their arguments.
5874 The result of functions returning arrays is stored in a temporary outside
5875 the loop, so that the function is only called once. Hence we do not need
5876 to walk their arguments. */
5878 static gfc_ss *
5879 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
5881 gfc_ss *newss;
5882 gfc_intrinsic_sym *isym;
5883 gfc_symbol *sym;
5885 isym = expr->value.function.isym;
5887 /* Handle intrinsic functions separately. */
5888 if (isym)
5889 return gfc_walk_intrinsic_function (ss, expr, isym);
5891 sym = expr->value.function.esym;
5892 if (!sym)
5893 sym = expr->symtree->n.sym;
5895 /* A function that returns arrays. */
5896 if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
5898 newss = gfc_get_ss ();
5899 newss->type = GFC_SS_FUNCTION;
5900 newss->expr = expr;
5901 newss->next = ss;
5902 newss->data.info.dimen = expr->rank;
5903 return newss;
5906 /* Walk the parameters of an elemental function. For now we always pass
5907 by reference. */
5908 if (sym->attr.elemental)
5909 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
5910 GFC_SS_REFERENCE);
5912 /* Scalar functions are OK as these are evaluated outside the scalarization
5913 loop. Pass back and let the caller deal with it. */
5914 return ss;
5918 /* An array temporary is constructed for array constructors. */
5920 static gfc_ss *
5921 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
5923 gfc_ss *newss;
5924 int n;
5926 newss = gfc_get_ss ();
5927 newss->type = GFC_SS_CONSTRUCTOR;
5928 newss->expr = expr;
5929 newss->next = ss;
5930 newss->data.info.dimen = expr->rank;
5931 for (n = 0; n < expr->rank; n++)
5932 newss->data.info.dim[n] = n;
5934 return newss;
5938 /* Walk an expression. Add walked expressions to the head of the SS chain.
5939 A wholly scalar expression will not be added. */
5941 static gfc_ss *
5942 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
5944 gfc_ss *head;
5946 switch (expr->expr_type)
5948 case EXPR_VARIABLE:
5949 head = gfc_walk_variable_expr (ss, expr);
5950 return head;
5952 case EXPR_OP:
5953 head = gfc_walk_op_expr (ss, expr);
5954 return head;
5956 case EXPR_FUNCTION:
5957 head = gfc_walk_function_expr (ss, expr);
5958 return head;
5960 case EXPR_CONSTANT:
5961 case EXPR_NULL:
5962 case EXPR_STRUCTURE:
5963 /* Pass back and let the caller deal with it. */
5964 break;
5966 case EXPR_ARRAY:
5967 head = gfc_walk_array_constructor (ss, expr);
5968 return head;
5970 case EXPR_SUBSTRING:
5971 /* Pass back and let the caller deal with it. */
5972 break;
5974 default:
5975 internal_error ("bad expression type during walk (%d)",
5976 expr->expr_type);
5978 return ss;
5982 /* Entry point for expression walking.
5983 A return value equal to the passed chain means this is
5984 a scalar expression. It is up to the caller to take whatever action is
5985 necessary to translate these. */
5987 gfc_ss *
5988 gfc_walk_expr (gfc_expr * expr)
5990 gfc_ss *res;
5992 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
5993 return gfc_reverse_ss (res);