Check in tree-dce enh to trunk
[official-gcc.git] / gcc / fortran / trans-array.c
blob784f1bc40d013735582a854bc3e900bd18c3d4fc
1 /* Array translation routines
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
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 = fold_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 = fold_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 = fold_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 fold_build3 (COMPONENT_REF, TREE_TYPE (field),
215 desc, field, NULL_TREE);
218 tree
219 gfc_conv_descriptor_dtype (tree desc)
221 tree field;
222 tree type;
224 type = TREE_TYPE (desc);
225 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
227 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
228 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
230 return fold_build3 (COMPONENT_REF, TREE_TYPE (field),
231 desc, field, NULL_TREE);
234 static tree
235 gfc_conv_descriptor_dimension (tree desc, tree dim)
237 tree field;
238 tree type;
239 tree tmp;
241 type = TREE_TYPE (desc);
242 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
244 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
245 gcc_assert (field != NULL_TREE
246 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
247 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
249 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
250 desc, field, NULL_TREE);
251 tmp = gfc_build_array_ref (tmp, dim, NULL);
252 return tmp;
255 tree
256 gfc_conv_descriptor_stride (tree desc, tree dim)
258 tree tmp;
259 tree field;
261 tmp = gfc_conv_descriptor_dimension (desc, dim);
262 field = TYPE_FIELDS (TREE_TYPE (tmp));
263 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
264 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
266 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
267 tmp, field, NULL_TREE);
268 return tmp;
271 tree
272 gfc_conv_descriptor_lbound (tree desc, tree dim)
274 tree tmp;
275 tree field;
277 tmp = gfc_conv_descriptor_dimension (desc, dim);
278 field = TYPE_FIELDS (TREE_TYPE (tmp));
279 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
280 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
282 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
283 tmp, field, NULL_TREE);
284 return tmp;
287 tree
288 gfc_conv_descriptor_ubound (tree desc, tree dim)
290 tree tmp;
291 tree field;
293 tmp = gfc_conv_descriptor_dimension (desc, dim);
294 field = TYPE_FIELDS (TREE_TYPE (tmp));
295 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
296 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
298 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
299 tmp, field, NULL_TREE);
300 return tmp;
304 /* Build a null array descriptor constructor. */
306 tree
307 gfc_build_null_descriptor (tree type)
309 tree field;
310 tree tmp;
312 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
313 gcc_assert (DATA_FIELD == 0);
314 field = TYPE_FIELDS (type);
316 /* Set a NULL data pointer. */
317 tmp = build_constructor_single (type, field, null_pointer_node);
318 TREE_CONSTANT (tmp) = 1;
319 /* All other fields are ignored. */
321 return tmp;
325 /* Cleanup those #defines. */
327 #undef DATA_FIELD
328 #undef OFFSET_FIELD
329 #undef DTYPE_FIELD
330 #undef DIMENSION_FIELD
331 #undef STRIDE_SUBFIELD
332 #undef LBOUND_SUBFIELD
333 #undef UBOUND_SUBFIELD
336 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
337 flags & 1 = Main loop body.
338 flags & 2 = temp copy loop. */
340 void
341 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
343 for (; ss != gfc_ss_terminator; ss = ss->next)
344 ss->useflags = flags;
347 static void gfc_free_ss (gfc_ss *);
350 /* Free a gfc_ss chain. */
352 static void
353 gfc_free_ss_chain (gfc_ss * ss)
355 gfc_ss *next;
357 while (ss != gfc_ss_terminator)
359 gcc_assert (ss != NULL);
360 next = ss->next;
361 gfc_free_ss (ss);
362 ss = next;
367 /* Free a SS. */
369 static void
370 gfc_free_ss (gfc_ss * ss)
372 int n;
374 switch (ss->type)
376 case GFC_SS_SECTION:
377 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
379 if (ss->data.info.subscript[n])
380 gfc_free_ss_chain (ss->data.info.subscript[n]);
382 break;
384 default:
385 break;
388 gfc_free (ss);
392 /* Free all the SS associated with a loop. */
394 void
395 gfc_cleanup_loop (gfc_loopinfo * loop)
397 gfc_ss *ss;
398 gfc_ss *next;
400 ss = loop->ss;
401 while (ss != gfc_ss_terminator)
403 gcc_assert (ss != NULL);
404 next = ss->loop_chain;
405 gfc_free_ss (ss);
406 ss = next;
411 /* Associate a SS chain with a loop. */
413 void
414 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
416 gfc_ss *ss;
418 if (head == gfc_ss_terminator)
419 return;
421 ss = head;
422 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
424 if (ss->next == gfc_ss_terminator)
425 ss->loop_chain = loop->ss;
426 else
427 ss->loop_chain = ss->next;
429 gcc_assert (ss == gfc_ss_terminator);
430 loop->ss = head;
434 /* Generate an initializer for a static pointer or allocatable array. */
436 void
437 gfc_trans_static_array_pointer (gfc_symbol * sym)
439 tree type;
441 gcc_assert (TREE_STATIC (sym->backend_decl));
442 /* Just zero the data member. */
443 type = TREE_TYPE (sym->backend_decl);
444 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
448 /* If the bounds of SE's loop have not yet been set, see if they can be
449 determined from array spec AS, which is the array spec of a called
450 function. MAPPING maps the callee's dummy arguments to the values
451 that the caller is passing. Add any initialization and finalization
452 code to SE. */
454 void
455 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
456 gfc_se * se, gfc_array_spec * as)
458 int n, dim;
459 gfc_se tmpse;
460 tree lower;
461 tree upper;
462 tree tmp;
464 if (as && as->type == AS_EXPLICIT)
465 for (dim = 0; dim < se->loop->dimen; dim++)
467 n = se->loop->order[dim];
468 if (se->loop->to[n] == NULL_TREE)
470 /* Evaluate the lower bound. */
471 gfc_init_se (&tmpse, NULL);
472 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
473 gfc_add_block_to_block (&se->pre, &tmpse.pre);
474 gfc_add_block_to_block (&se->post, &tmpse.post);
475 lower = tmpse.expr;
477 /* ...and the upper bound. */
478 gfc_init_se (&tmpse, NULL);
479 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
480 gfc_add_block_to_block (&se->pre, &tmpse.pre);
481 gfc_add_block_to_block (&se->post, &tmpse.post);
482 upper = tmpse.expr;
484 /* Set the upper bound of the loop to UPPER - LOWER. */
485 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
486 tmp = gfc_evaluate_now (tmp, &se->pre);
487 se->loop->to[n] = tmp;
493 /* Generate code to allocate an array temporary, or create a variable to
494 hold the data. If size is NULL, zero the descriptor so that the
495 callee will allocate the array. If DEALLOC is true, also generate code to
496 free the array afterwards.
498 Initialization code is added to PRE and finalization code to POST.
499 DYNAMIC is true if the caller may want to extend the array later
500 using realloc. This prevents us from putting the array on the stack. */
502 static void
503 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
504 gfc_ss_info * info, tree size, tree nelem,
505 bool dynamic, bool dealloc)
507 tree tmp;
508 tree desc;
509 bool onstack;
511 desc = info->descriptor;
512 info->offset = gfc_index_zero_node;
513 if (size == NULL_TREE || integer_zerop (size))
515 /* A callee allocated array. */
516 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
517 onstack = FALSE;
519 else
521 /* Allocate the temporary. */
522 onstack = !dynamic && gfc_can_put_var_on_stack (size);
524 if (onstack)
526 /* Make a temporary variable to hold the data. */
527 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (nelem), nelem,
528 gfc_index_one_node);
529 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
530 tmp);
531 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
532 tmp);
533 tmp = gfc_create_var (tmp, "A");
534 tmp = build_fold_addr_expr (tmp);
535 gfc_conv_descriptor_data_set (pre, desc, tmp);
537 else
539 /* Allocate memory to hold the data. */
540 tmp = gfc_call_malloc (pre, NULL, size);
541 tmp = gfc_evaluate_now (tmp, pre);
542 gfc_conv_descriptor_data_set (pre, desc, tmp);
545 info->data = gfc_conv_descriptor_data_get (desc);
547 /* The offset is zero because we create temporaries with a zero
548 lower bound. */
549 tmp = gfc_conv_descriptor_offset (desc);
550 gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
552 if (dealloc && !onstack)
554 /* Free the temporary. */
555 tmp = gfc_conv_descriptor_data_get (desc);
556 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
557 gfc_add_expr_to_block (post, tmp);
562 /* Generate code to create and initialize the descriptor for a temporary
563 array. This is used for both temporaries needed by the scalarizer, and
564 functions returning arrays. Adjusts the loop variables to be
565 zero-based, and calculates the loop bounds for callee allocated arrays.
566 Allocate the array unless it's callee allocated (we have a callee
567 allocated array if 'callee_alloc' is true, or if loop->to[n] is
568 NULL_TREE for any n). Also fills in the descriptor, data and offset
569 fields of info if known. Returns the size of the array, or NULL for a
570 callee allocated array.
572 PRE, POST, DYNAMIC and DEALLOC are as for gfc_trans_allocate_array_storage.
575 tree
576 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
577 gfc_loopinfo * loop, gfc_ss_info * info,
578 tree eltype, bool dynamic, bool dealloc,
579 bool callee_alloc)
581 tree type;
582 tree desc;
583 tree tmp;
584 tree size;
585 tree nelem;
586 tree cond;
587 tree or_expr;
588 int n;
589 int dim;
591 gcc_assert (info->dimen > 0);
592 /* Set the lower bound to zero. */
593 for (dim = 0; dim < info->dimen; dim++)
595 n = loop->order[dim];
596 /* TODO: Investigate why "if (n < loop->temp_dim)
597 gcc_assert (integer_zerop (loop->from[n]));" fails here. */
598 if (n >= loop->temp_dim)
600 /* Callee allocated arrays may not have a known bound yet. */
601 if (loop->to[n])
602 loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
603 loop->to[n], loop->from[n]);
604 loop->from[n] = gfc_index_zero_node;
607 info->delta[dim] = gfc_index_zero_node;
608 info->start[dim] = gfc_index_zero_node;
609 info->end[dim] = gfc_index_zero_node;
610 info->stride[dim] = gfc_index_one_node;
611 info->dim[dim] = dim;
614 /* Initialize the descriptor. */
615 type =
616 gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1,
617 GFC_ARRAY_UNKNOWN);
618 desc = gfc_create_var (type, "atmp");
619 GFC_DECL_PACKED_ARRAY (desc) = 1;
621 info->descriptor = desc;
622 size = gfc_index_one_node;
624 /* Fill in the array dtype. */
625 tmp = gfc_conv_descriptor_dtype (desc);
626 gfc_add_modify_expr (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
629 Fill in the bounds and stride. This is a packed array, so:
631 size = 1;
632 for (n = 0; n < rank; n++)
634 stride[n] = size
635 delta = ubound[n] + 1 - lbound[n];
636 size = size * delta;
638 size = size * sizeof(element);
641 or_expr = NULL_TREE;
643 for (n = 0; n < info->dimen; n++)
645 if (loop->to[n] == NULL_TREE)
647 /* For a callee allocated array express the loop bounds in terms
648 of the descriptor fields. */
649 tmp =
650 fold_build2 (MINUS_EXPR, gfc_array_index_type,
651 gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
652 gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
653 loop->to[n] = tmp;
654 size = NULL_TREE;
655 continue;
658 /* Store the stride and bound components in the descriptor. */
659 tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
660 gfc_add_modify_expr (pre, tmp, size);
662 tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
663 gfc_add_modify_expr (pre, tmp, gfc_index_zero_node);
665 tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
666 gfc_add_modify_expr (pre, tmp, loop->to[n]);
668 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
669 loop->to[n], gfc_index_one_node);
671 /* Check whether the size for this dimension is negative. */
672 cond = fold_build2 (LE_EXPR, boolean_type_node, tmp,
673 gfc_index_zero_node);
674 cond = gfc_evaluate_now (cond, pre);
676 if (n == 0)
677 or_expr = cond;
678 else
679 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
681 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
682 size = gfc_evaluate_now (size, pre);
685 /* Get the size of the array. */
687 if (size && !callee_alloc)
689 /* If or_expr is true, then the extent in at least one
690 dimension is zero and the size is set to zero. */
691 size = fold_build3 (COND_EXPR, gfc_array_index_type,
692 or_expr, gfc_index_zero_node, size);
694 nelem = size;
695 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
696 fold_convert (gfc_array_index_type,
697 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
699 else
701 nelem = size;
702 size = NULL_TREE;
705 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, dynamic,
706 dealloc);
708 if (info->dimen > loop->temp_dim)
709 loop->temp_dim = info->dimen;
711 return size;
715 /* Generate code to transpose array EXPR by creating a new descriptor
716 in which the dimension specifications have been reversed. */
718 void
719 gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
721 tree dest, src, dest_index, src_index;
722 gfc_loopinfo *loop;
723 gfc_ss_info *dest_info, *src_info;
724 gfc_ss *dest_ss, *src_ss;
725 gfc_se src_se;
726 int n;
728 loop = se->loop;
730 src_ss = gfc_walk_expr (expr);
731 dest_ss = se->ss;
733 src_info = &src_ss->data.info;
734 dest_info = &dest_ss->data.info;
735 gcc_assert (dest_info->dimen == 2);
736 gcc_assert (src_info->dimen == 2);
738 /* Get a descriptor for EXPR. */
739 gfc_init_se (&src_se, NULL);
740 gfc_conv_expr_descriptor (&src_se, expr, src_ss);
741 gfc_add_block_to_block (&se->pre, &src_se.pre);
742 gfc_add_block_to_block (&se->post, &src_se.post);
743 src = src_se.expr;
745 /* Allocate a new descriptor for the return value. */
746 dest = gfc_create_var (TREE_TYPE (src), "atmp");
747 dest_info->descriptor = dest;
748 se->expr = dest;
750 /* Copy across the dtype field. */
751 gfc_add_modify_expr (&se->pre,
752 gfc_conv_descriptor_dtype (dest),
753 gfc_conv_descriptor_dtype (src));
755 /* Copy the dimension information, renumbering dimension 1 to 0 and
756 0 to 1. */
757 for (n = 0; n < 2; n++)
759 dest_info->delta[n] = gfc_index_zero_node;
760 dest_info->start[n] = gfc_index_zero_node;
761 dest_info->end[n] = gfc_index_zero_node;
762 dest_info->stride[n] = gfc_index_one_node;
763 dest_info->dim[n] = n;
765 dest_index = gfc_rank_cst[n];
766 src_index = gfc_rank_cst[1 - n];
768 gfc_add_modify_expr (&se->pre,
769 gfc_conv_descriptor_stride (dest, dest_index),
770 gfc_conv_descriptor_stride (src, src_index));
772 gfc_add_modify_expr (&se->pre,
773 gfc_conv_descriptor_lbound (dest, dest_index),
774 gfc_conv_descriptor_lbound (src, src_index));
776 gfc_add_modify_expr (&se->pre,
777 gfc_conv_descriptor_ubound (dest, dest_index),
778 gfc_conv_descriptor_ubound (src, src_index));
780 if (!loop->to[n])
782 gcc_assert (integer_zerop (loop->from[n]));
783 loop->to[n] =
784 fold_build2 (MINUS_EXPR, gfc_array_index_type,
785 gfc_conv_descriptor_ubound (dest, dest_index),
786 gfc_conv_descriptor_lbound (dest, dest_index));
790 /* Copy the data pointer. */
791 dest_info->data = gfc_conv_descriptor_data_get (src);
792 gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);
794 /* Copy the offset. This is not changed by transposition; the top-left
795 element is still at the same offset as before, except where the loop
796 starts at zero. */
797 if (!integer_zerop (loop->from[0]))
798 dest_info->offset = gfc_conv_descriptor_offset (src);
799 else
800 dest_info->offset = gfc_index_zero_node;
802 gfc_add_modify_expr (&se->pre,
803 gfc_conv_descriptor_offset (dest),
804 dest_info->offset);
806 if (dest_info->dimen > loop->temp_dim)
807 loop->temp_dim = dest_info->dimen;
811 /* Return the number of iterations in a loop that starts at START,
812 ends at END, and has step STEP. */
814 static tree
815 gfc_get_iteration_count (tree start, tree end, tree step)
817 tree tmp;
818 tree type;
820 type = TREE_TYPE (step);
821 tmp = fold_build2 (MINUS_EXPR, type, end, start);
822 tmp = fold_build2 (FLOOR_DIV_EXPR, type, tmp, step);
823 tmp = fold_build2 (PLUS_EXPR, type, tmp, build_int_cst (type, 1));
824 tmp = fold_build2 (MAX_EXPR, type, tmp, build_int_cst (type, 0));
825 return fold_convert (gfc_array_index_type, tmp);
829 /* Extend the data in array DESC by EXTRA elements. */
831 static void
832 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
834 tree arg0, arg1;
835 tree tmp;
836 tree size;
837 tree ubound;
839 if (integer_zerop (extra))
840 return;
842 ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
844 /* Add EXTRA to the upper bound. */
845 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
846 gfc_add_modify_expr (pblock, ubound, tmp);
848 /* Get the value of the current data pointer. */
849 arg0 = gfc_conv_descriptor_data_get (desc);
851 /* Calculate the new array size. */
852 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
853 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
854 ubound, gfc_index_one_node);
855 arg1 = fold_build2 (MULT_EXPR, size_type_node,
856 fold_convert (size_type_node, tmp),
857 fold_convert (size_type_node, size));
859 /* Call the realloc() function. */
860 tmp = gfc_call_realloc (pblock, arg0, arg1);
861 gfc_conv_descriptor_data_set (pblock, desc, tmp);
865 /* Return true if the bounds of iterator I can only be determined
866 at run time. */
868 static inline bool
869 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
871 return (i->start->expr_type != EXPR_CONSTANT
872 || i->end->expr_type != EXPR_CONSTANT
873 || i->step->expr_type != EXPR_CONSTANT);
877 /* Split the size of constructor element EXPR into the sum of two terms,
878 one of which can be determined at compile time and one of which must
879 be calculated at run time. Set *SIZE to the former and return true
880 if the latter might be nonzero. */
882 static bool
883 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
885 if (expr->expr_type == EXPR_ARRAY)
886 return gfc_get_array_constructor_size (size, expr->value.constructor);
887 else if (expr->rank > 0)
889 /* Calculate everything at run time. */
890 mpz_set_ui (*size, 0);
891 return true;
893 else
895 /* A single element. */
896 mpz_set_ui (*size, 1);
897 return false;
902 /* Like gfc_get_array_constructor_element_size, but applied to the whole
903 of array constructor C. */
905 static bool
906 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
908 gfc_iterator *i;
909 mpz_t val;
910 mpz_t len;
911 bool dynamic;
913 mpz_set_ui (*size, 0);
914 mpz_init (len);
915 mpz_init (val);
917 dynamic = false;
918 for (; c; c = c->next)
920 i = c->iterator;
921 if (i && gfc_iterator_has_dynamic_bounds (i))
922 dynamic = true;
923 else
925 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
926 if (i)
928 /* Multiply the static part of the element size by the
929 number of iterations. */
930 mpz_sub (val, i->end->value.integer, i->start->value.integer);
931 mpz_fdiv_q (val, val, i->step->value.integer);
932 mpz_add_ui (val, val, 1);
933 if (mpz_sgn (val) > 0)
934 mpz_mul (len, len, val);
935 else
936 mpz_set_ui (len, 0);
938 mpz_add (*size, *size, len);
941 mpz_clear (len);
942 mpz_clear (val);
943 return dynamic;
947 /* Make sure offset is a variable. */
949 static void
950 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
951 tree * offsetvar)
953 /* We should have already created the offset variable. We cannot
954 create it here because we may be in an inner scope. */
955 gcc_assert (*offsetvar != NULL_TREE);
956 gfc_add_modify_expr (pblock, *offsetvar, *poffset);
957 *poffset = *offsetvar;
958 TREE_USED (*offsetvar) = 1;
962 /* Variables needed for bounds-checking. */
963 static bool first_len;
964 static tree first_len_val;
965 static bool typespec_chararray_ctor;
967 static void
968 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
969 tree offset, gfc_se * se, gfc_expr * expr)
971 tree tmp;
972 tree esize;
974 gfc_conv_expr (se, expr);
976 /* Store the value. */
977 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
978 tmp = gfc_build_array_ref (tmp, offset, NULL);
980 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
981 esize = fold_convert (gfc_charlen_type_node, esize);
983 if (expr->ts.type == BT_CHARACTER)
985 gfc_conv_string_parameter (se);
986 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
988 /* The temporary is an array of pointers. */
989 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
990 gfc_add_modify_expr (&se->pre, tmp, se->expr);
992 else
994 /* The temporary is an array of string values. */
995 tmp = gfc_build_addr_expr (pchar_type_node, tmp);
996 /* We know the temporary and the value will be the same length,
997 so can use memcpy. */
998 gfc_trans_string_copy (&se->pre, esize, tmp,
999 se->string_length,
1000 se->expr);
1002 if (flag_bounds_check && !typespec_chararray_ctor)
1004 if (first_len)
1006 gfc_add_modify_expr (&se->pre, first_len_val,
1007 se->string_length);
1008 first_len = false;
1010 else
1012 /* Verify that all constructor elements are of the same
1013 length. */
1014 tree cond = fold_build2 (NE_EXPR, boolean_type_node,
1015 first_len_val, se->string_length);
1016 gfc_trans_runtime_check
1017 (cond, &se->pre, &expr->where,
1018 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1019 fold_convert (long_integer_type_node, first_len_val),
1020 fold_convert (long_integer_type_node, se->string_length));
1024 else
1026 /* TODO: Should the frontend already have done this conversion? */
1027 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1028 gfc_add_modify_expr (&se->pre, tmp, se->expr);
1031 gfc_add_block_to_block (pblock, &se->pre);
1032 gfc_add_block_to_block (pblock, &se->post);
1036 /* Add the contents of an array to the constructor. DYNAMIC is as for
1037 gfc_trans_array_constructor_value. */
1039 static void
1040 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1041 tree type ATTRIBUTE_UNUSED,
1042 tree desc, gfc_expr * expr,
1043 tree * poffset, tree * offsetvar,
1044 bool dynamic)
1046 gfc_se se;
1047 gfc_ss *ss;
1048 gfc_loopinfo loop;
1049 stmtblock_t body;
1050 tree tmp;
1051 tree size;
1052 int n;
1054 /* We need this to be a variable so we can increment it. */
1055 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1057 gfc_init_se (&se, NULL);
1059 /* Walk the array expression. */
1060 ss = gfc_walk_expr (expr);
1061 gcc_assert (ss != gfc_ss_terminator);
1063 /* Initialize the scalarizer. */
1064 gfc_init_loopinfo (&loop);
1065 gfc_add_ss_to_loop (&loop, ss);
1067 /* Initialize the loop. */
1068 gfc_conv_ss_startstride (&loop);
1069 gfc_conv_loop_setup (&loop);
1071 /* Make sure the constructed array has room for the new data. */
1072 if (dynamic)
1074 /* Set SIZE to the total number of elements in the subarray. */
1075 size = gfc_index_one_node;
1076 for (n = 0; n < loop.dimen; n++)
1078 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1079 gfc_index_one_node);
1080 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1083 /* Grow the constructed array by SIZE elements. */
1084 gfc_grow_array (&loop.pre, desc, size);
1087 /* Make the loop body. */
1088 gfc_mark_ss_chain_used (ss, 1);
1089 gfc_start_scalarized_body (&loop, &body);
1090 gfc_copy_loopinfo_to_se (&se, &loop);
1091 se.ss = ss;
1093 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1094 gcc_assert (se.ss == gfc_ss_terminator);
1096 /* Increment the offset. */
1097 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1098 *poffset, gfc_index_one_node);
1099 gfc_add_modify_expr (&body, *poffset, tmp);
1101 /* Finish the loop. */
1102 gfc_trans_scalarizing_loops (&loop, &body);
1103 gfc_add_block_to_block (&loop.pre, &loop.post);
1104 tmp = gfc_finish_block (&loop.pre);
1105 gfc_add_expr_to_block (pblock, tmp);
1107 gfc_cleanup_loop (&loop);
1111 /* Assign the values to the elements of an array constructor. DYNAMIC
1112 is true if descriptor DESC only contains enough data for the static
1113 size calculated by gfc_get_array_constructor_size. When true, memory
1114 for the dynamic parts must be allocated using realloc. */
1116 static void
1117 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1118 tree desc, gfc_constructor * c,
1119 tree * poffset, tree * offsetvar,
1120 bool dynamic)
1122 tree tmp;
1123 stmtblock_t body;
1124 gfc_se se;
1125 mpz_t size;
1127 mpz_init (size);
1128 for (; c; c = c->next)
1130 /* If this is an iterator or an array, the offset must be a variable. */
1131 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1132 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1134 gfc_start_block (&body);
1136 if (c->expr->expr_type == EXPR_ARRAY)
1138 /* Array constructors can be nested. */
1139 gfc_trans_array_constructor_value (&body, type, desc,
1140 c->expr->value.constructor,
1141 poffset, offsetvar, dynamic);
1143 else if (c->expr->rank > 0)
1145 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1146 poffset, offsetvar, dynamic);
1148 else
1150 /* This code really upsets the gimplifier so don't bother for now. */
1151 gfc_constructor *p;
1152 HOST_WIDE_INT n;
1153 HOST_WIDE_INT size;
1155 p = c;
1156 n = 0;
1157 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1159 p = p->next;
1160 n++;
1162 if (n < 4)
1164 /* Scalar values. */
1165 gfc_init_se (&se, NULL);
1166 gfc_trans_array_ctor_element (&body, desc, *poffset,
1167 &se, c->expr);
1169 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1170 *poffset, gfc_index_one_node);
1172 else
1174 /* Collect multiple scalar constants into a constructor. */
1175 tree list;
1176 tree init;
1177 tree bound;
1178 tree tmptype;
1180 p = c;
1181 list = NULL_TREE;
1182 /* Count the number of consecutive scalar constants. */
1183 while (p && !(p->iterator
1184 || p->expr->expr_type != EXPR_CONSTANT))
1186 gfc_init_se (&se, NULL);
1187 gfc_conv_constant (&se, p->expr);
1188 if (p->expr->ts.type == BT_CHARACTER
1189 && POINTER_TYPE_P (type))
1191 /* For constant character array constructors we build
1192 an array of pointers. */
1193 se.expr = gfc_build_addr_expr (pchar_type_node,
1194 se.expr);
1197 list = tree_cons (NULL_TREE, se.expr, list);
1198 c = p;
1199 p = p->next;
1202 bound = build_int_cst (NULL_TREE, n - 1);
1203 /* Create an array type to hold them. */
1204 tmptype = build_range_type (gfc_array_index_type,
1205 gfc_index_zero_node, bound);
1206 tmptype = build_array_type (type, tmptype);
1208 init = build_constructor_from_list (tmptype, nreverse (list));
1209 TREE_CONSTANT (init) = 1;
1210 TREE_STATIC (init) = 1;
1211 /* Create a static variable to hold the data. */
1212 tmp = gfc_create_var (tmptype, "data");
1213 TREE_STATIC (tmp) = 1;
1214 TREE_CONSTANT (tmp) = 1;
1215 TREE_READONLY (tmp) = 1;
1216 DECL_INITIAL (tmp) = init;
1217 init = tmp;
1219 /* Use BUILTIN_MEMCPY to assign the values. */
1220 tmp = gfc_conv_descriptor_data_get (desc);
1221 tmp = build_fold_indirect_ref (tmp);
1222 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1223 tmp = build_fold_addr_expr (tmp);
1224 init = build_fold_addr_expr (init);
1226 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1227 bound = build_int_cst (NULL_TREE, n * size);
1228 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
1229 tmp, init, bound);
1230 gfc_add_expr_to_block (&body, tmp);
1232 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1233 *poffset,
1234 build_int_cst (gfc_array_index_type, n));
1236 if (!INTEGER_CST_P (*poffset))
1238 gfc_add_modify_expr (&body, *offsetvar, *poffset);
1239 *poffset = *offsetvar;
1243 /* The frontend should already have done any expansions possible
1244 at compile-time. */
1245 if (!c->iterator)
1247 /* Pass the code as is. */
1248 tmp = gfc_finish_block (&body);
1249 gfc_add_expr_to_block (pblock, tmp);
1251 else
1253 /* Build the implied do-loop. */
1254 tree cond;
1255 tree end;
1256 tree step;
1257 tree loopvar;
1258 tree exit_label;
1259 tree loopbody;
1260 tree tmp2;
1261 tree tmp_loopvar;
1263 loopbody = gfc_finish_block (&body);
1265 if (c->iterator->var->symtree->n.sym->backend_decl)
1267 gfc_init_se (&se, NULL);
1268 gfc_conv_expr (&se, c->iterator->var);
1269 gfc_add_block_to_block (pblock, &se.pre);
1270 loopvar = se.expr;
1272 else
1274 /* If the iterator appears in a specification expression in
1275 an interface mapping, we need to make a temp for the loop
1276 variable because it is not declared locally. */
1277 loopvar = gfc_typenode_for_spec (&c->iterator->var->ts);
1278 loopvar = gfc_create_var (loopvar, "loopvar");
1281 /* Make a temporary, store the current value in that
1282 and return it, once the loop is done. */
1283 tmp_loopvar = gfc_create_var (TREE_TYPE (loopvar), "loopvar");
1284 gfc_add_modify_expr (pblock, tmp_loopvar, loopvar);
1286 /* Initialize the loop. */
1287 gfc_init_se (&se, NULL);
1288 gfc_conv_expr_val (&se, c->iterator->start);
1289 gfc_add_block_to_block (pblock, &se.pre);
1290 gfc_add_modify_expr (pblock, loopvar, se.expr);
1292 gfc_init_se (&se, NULL);
1293 gfc_conv_expr_val (&se, c->iterator->end);
1294 gfc_add_block_to_block (pblock, &se.pre);
1295 end = gfc_evaluate_now (se.expr, pblock);
1297 gfc_init_se (&se, NULL);
1298 gfc_conv_expr_val (&se, c->iterator->step);
1299 gfc_add_block_to_block (pblock, &se.pre);
1300 step = gfc_evaluate_now (se.expr, pblock);
1302 /* If this array expands dynamically, and the number of iterations
1303 is not constant, we won't have allocated space for the static
1304 part of C->EXPR's size. Do that now. */
1305 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1307 /* Get the number of iterations. */
1308 tmp = gfc_get_iteration_count (loopvar, end, step);
1310 /* Get the static part of C->EXPR's size. */
1311 gfc_get_array_constructor_element_size (&size, c->expr);
1312 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1314 /* Grow the array by TMP * TMP2 elements. */
1315 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
1316 gfc_grow_array (pblock, desc, tmp);
1319 /* Generate the loop body. */
1320 exit_label = gfc_build_label_decl (NULL_TREE);
1321 gfc_start_block (&body);
1323 /* Generate the exit condition. Depending on the sign of
1324 the step variable we have to generate the correct
1325 comparison. */
1326 tmp = fold_build2 (GT_EXPR, boolean_type_node, step,
1327 build_int_cst (TREE_TYPE (step), 0));
1328 cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
1329 fold_build2 (GT_EXPR, boolean_type_node,
1330 loopvar, end),
1331 fold_build2 (LT_EXPR, boolean_type_node,
1332 loopvar, end));
1333 tmp = build1_v (GOTO_EXPR, exit_label);
1334 TREE_USED (exit_label) = 1;
1335 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1336 gfc_add_expr_to_block (&body, tmp);
1338 /* The main loop body. */
1339 gfc_add_expr_to_block (&body, loopbody);
1341 /* Increase loop variable by step. */
1342 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
1343 gfc_add_modify_expr (&body, loopvar, tmp);
1345 /* Finish the loop. */
1346 tmp = gfc_finish_block (&body);
1347 tmp = build1_v (LOOP_EXPR, tmp);
1348 gfc_add_expr_to_block (pblock, tmp);
1350 /* Add the exit label. */
1351 tmp = build1_v (LABEL_EXPR, exit_label);
1352 gfc_add_expr_to_block (pblock, tmp);
1354 /* Restore the original value of the loop counter. */
1355 gfc_add_modify_expr (pblock, loopvar, tmp_loopvar);
1358 mpz_clear (size);
1362 /* Figure out the string length of a variable reference expression.
1363 Used by get_array_ctor_strlen. */
1365 static void
1366 get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1368 gfc_ref *ref;
1369 gfc_typespec *ts;
1370 mpz_t char_len;
1372 /* Don't bother if we already know the length is a constant. */
1373 if (*len && INTEGER_CST_P (*len))
1374 return;
1376 ts = &expr->symtree->n.sym->ts;
1377 for (ref = expr->ref; ref; ref = ref->next)
1379 switch (ref->type)
1381 case REF_ARRAY:
1382 /* Array references don't change the string length. */
1383 break;
1385 case REF_COMPONENT:
1386 /* Use the length of the component. */
1387 ts = &ref->u.c.component->ts;
1388 break;
1390 case REF_SUBSTRING:
1391 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1392 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1393 break;
1394 mpz_init_set_ui (char_len, 1);
1395 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1396 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1397 *len = gfc_conv_mpz_to_tree (char_len,
1398 gfc_default_character_kind);
1399 *len = convert (gfc_charlen_type_node, *len);
1400 mpz_clear (char_len);
1401 return;
1403 default:
1404 /* TODO: Substrings are tricky because we can't evaluate the
1405 expression more than once. For now we just give up, and hope
1406 we can figure it out elsewhere. */
1407 return;
1411 *len = ts->cl->backend_decl;
1415 /* A catch-all to obtain the string length for anything that is not a
1416 constant, array or variable. */
1417 static void
1418 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1420 gfc_se se;
1421 gfc_ss *ss;
1423 /* Don't bother if we already know the length is a constant. */
1424 if (*len && INTEGER_CST_P (*len))
1425 return;
1427 if (!e->ref && e->ts.cl && e->ts.cl->length
1428 && e->ts.cl->length->expr_type == EXPR_CONSTANT)
1430 /* This is easy. */
1431 gfc_conv_const_charlen (e->ts.cl);
1432 *len = e->ts.cl->backend_decl;
1434 else
1436 /* Otherwise, be brutal even if inefficient. */
1437 ss = gfc_walk_expr (e);
1438 gfc_init_se (&se, NULL);
1440 /* No function call, in case of side effects. */
1441 se.no_function_call = 1;
1442 if (ss == gfc_ss_terminator)
1443 gfc_conv_expr (&se, e);
1444 else
1445 gfc_conv_expr_descriptor (&se, e, ss);
1447 /* Fix the value. */
1448 *len = gfc_evaluate_now (se.string_length, &se.pre);
1450 gfc_add_block_to_block (block, &se.pre);
1451 gfc_add_block_to_block (block, &se.post);
1453 e->ts.cl->backend_decl = *len;
1458 /* Figure out the string length of a character array constructor.
1459 Returns TRUE if all elements are character constants. */
1461 bool
1462 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
1464 bool is_const;
1466 is_const = TRUE;
1468 if (c == NULL)
1470 *len = build_int_cstu (gfc_charlen_type_node, 0);
1471 return is_const;
1474 for (; c; c = c->next)
1476 switch (c->expr->expr_type)
1478 case EXPR_CONSTANT:
1479 if (!(*len && INTEGER_CST_P (*len)))
1480 *len = build_int_cstu (gfc_charlen_type_node,
1481 c->expr->value.character.length);
1482 break;
1484 case EXPR_ARRAY:
1485 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1486 is_const = false;
1487 break;
1489 case EXPR_VARIABLE:
1490 is_const = false;
1491 get_array_ctor_var_strlen (c->expr, len);
1492 break;
1494 default:
1495 is_const = false;
1496 get_array_ctor_all_strlen (block, c->expr, len);
1497 break;
1501 return is_const;
1504 /* Check whether the array constructor C consists entirely of constant
1505 elements, and if so returns the number of those elements, otherwise
1506 return zero. Note, an empty or NULL array constructor returns zero. */
1508 unsigned HOST_WIDE_INT
1509 gfc_constant_array_constructor_p (gfc_constructor * c)
1511 unsigned HOST_WIDE_INT nelem = 0;
1513 while (c)
1515 if (c->iterator
1516 || c->expr->rank > 0
1517 || c->expr->expr_type != EXPR_CONSTANT)
1518 return 0;
1519 c = c->next;
1520 nelem++;
1522 return nelem;
1526 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1527 and the tree type of it's elements, TYPE, return a static constant
1528 variable that is compile-time initialized. */
1530 tree
1531 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1533 tree tmptype, list, init, tmp;
1534 HOST_WIDE_INT nelem;
1535 gfc_constructor *c;
1536 gfc_array_spec as;
1537 gfc_se se;
1538 int i;
1540 /* First traverse the constructor list, converting the constants
1541 to tree to build an initializer. */
1542 nelem = 0;
1543 list = NULL_TREE;
1544 c = expr->value.constructor;
1545 while (c)
1547 gfc_init_se (&se, NULL);
1548 gfc_conv_constant (&se, c->expr);
1549 if (c->expr->ts.type == BT_CHARACTER
1550 && POINTER_TYPE_P (type))
1551 se.expr = gfc_build_addr_expr (pchar_type_node, se.expr);
1552 list = tree_cons (NULL_TREE, se.expr, list);
1553 c = c->next;
1554 nelem++;
1557 /* Next determine the tree type for the array. We use the gfortran
1558 front-end's gfc_get_nodesc_array_type in order to create a suitable
1559 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1561 memset (&as, 0, sizeof (gfc_array_spec));
1563 as.rank = expr->rank;
1564 as.type = AS_EXPLICIT;
1565 if (!expr->shape)
1567 as.lower[0] = gfc_int_expr (0);
1568 as.upper[0] = gfc_int_expr (nelem - 1);
1570 else
1571 for (i = 0; i < expr->rank; i++)
1573 int tmp = (int) mpz_get_si (expr->shape[i]);
1574 as.lower[i] = gfc_int_expr (0);
1575 as.upper[i] = gfc_int_expr (tmp - 1);
1578 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
1580 init = build_constructor_from_list (tmptype, nreverse (list));
1582 TREE_CONSTANT (init) = 1;
1583 TREE_STATIC (init) = 1;
1585 tmp = gfc_create_var (tmptype, "A");
1586 TREE_STATIC (tmp) = 1;
1587 TREE_CONSTANT (tmp) = 1;
1588 TREE_READONLY (tmp) = 1;
1589 DECL_INITIAL (tmp) = init;
1591 return tmp;
1595 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1596 This mostly initializes the scalarizer state info structure with the
1597 appropriate values to directly use the array created by the function
1598 gfc_build_constant_array_constructor. */
1600 static void
1601 gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
1602 gfc_ss * ss, tree type)
1604 gfc_ss_info *info;
1605 tree tmp;
1606 int i;
1608 tmp = gfc_build_constant_array_constructor (ss->expr, type);
1610 info = &ss->data.info;
1612 info->descriptor = tmp;
1613 info->data = build_fold_addr_expr (tmp);
1614 info->offset = fold_build1 (NEGATE_EXPR, gfc_array_index_type,
1615 loop->from[0]);
1617 for (i = 0; i < info->dimen; i++)
1619 info->delta[i] = gfc_index_zero_node;
1620 info->start[i] = gfc_index_zero_node;
1621 info->end[i] = gfc_index_zero_node;
1622 info->stride[i] = gfc_index_one_node;
1623 info->dim[i] = i;
1626 if (info->dimen > loop->temp_dim)
1627 loop->temp_dim = info->dimen;
1630 /* Helper routine of gfc_trans_array_constructor to determine if the
1631 bounds of the loop specified by LOOP are constant and simple enough
1632 to use with gfc_trans_constant_array_constructor. Returns the
1633 the iteration count of the loop if suitable, and NULL_TREE otherwise. */
1635 static tree
1636 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1638 tree size = gfc_index_one_node;
1639 tree tmp;
1640 int i;
1642 for (i = 0; i < loop->dimen; i++)
1644 /* If the bounds aren't constant, return NULL_TREE. */
1645 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1646 return NULL_TREE;
1647 if (!integer_zerop (loop->from[i]))
1649 /* Only allow nonzero "from" in one-dimensional arrays. */
1650 if (loop->dimen != 1)
1651 return NULL_TREE;
1652 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1653 loop->to[i], loop->from[i]);
1655 else
1656 tmp = loop->to[i];
1657 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1658 tmp, gfc_index_one_node);
1659 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1662 return size;
1666 /* Array constructors are handled by constructing a temporary, then using that
1667 within the scalarization loop. This is not optimal, but seems by far the
1668 simplest method. */
1670 static void
1671 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
1673 gfc_constructor *c;
1674 tree offset;
1675 tree offsetvar;
1676 tree desc;
1677 tree type;
1678 tree loopfrom;
1679 bool dynamic;
1681 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
1682 typespec was given for the array constructor. */
1683 typespec_chararray_ctor = (ss->expr->ts.cl
1684 && ss->expr->ts.cl->length_from_typespec);
1686 if (flag_bounds_check && ss->expr->ts.type == BT_CHARACTER
1687 && !typespec_chararray_ctor)
1689 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1690 first_len = true;
1693 ss->data.info.dimen = loop->dimen;
1695 c = ss->expr->value.constructor;
1696 if (ss->expr->ts.type == BT_CHARACTER)
1698 bool const_string;
1700 /* get_array_ctor_strlen walks the elements of the constructor, if a
1701 typespec was given, we already know the string length and want the one
1702 specified there. */
1703 if (typespec_chararray_ctor && ss->expr->ts.cl->length
1704 && ss->expr->ts.cl->length->expr_type != EXPR_CONSTANT)
1706 gfc_se length_se;
1708 const_string = false;
1709 gfc_init_se (&length_se, NULL);
1710 gfc_conv_expr_type (&length_se, ss->expr->ts.cl->length,
1711 gfc_charlen_type_node);
1712 ss->string_length = length_se.expr;
1713 gfc_add_block_to_block (&loop->pre, &length_se.pre);
1714 gfc_add_block_to_block (&loop->post, &length_se.post);
1716 else
1717 const_string = get_array_ctor_strlen (&loop->pre, c,
1718 &ss->string_length);
1720 /* Complex character array constructors should have been taken care of
1721 and not end up here. */
1722 gcc_assert (ss->string_length);
1724 ss->expr->ts.cl->backend_decl = ss->string_length;
1726 type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1727 if (const_string)
1728 type = build_pointer_type (type);
1730 else
1731 type = gfc_typenode_for_spec (&ss->expr->ts);
1733 /* See if the constructor determines the loop bounds. */
1734 dynamic = false;
1736 if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
1738 /* We have a multidimensional parameter. */
1739 int n;
1740 for (n = 0; n < ss->expr->rank; n++)
1742 loop->from[n] = gfc_index_zero_node;
1743 loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
1744 gfc_index_integer_kind);
1745 loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1746 loop->to[n], gfc_index_one_node);
1750 if (loop->to[0] == NULL_TREE)
1752 mpz_t size;
1754 /* We should have a 1-dimensional, zero-based loop. */
1755 gcc_assert (loop->dimen == 1);
1756 gcc_assert (integer_zerop (loop->from[0]));
1758 /* Split the constructor size into a static part and a dynamic part.
1759 Allocate the static size up-front and record whether the dynamic
1760 size might be nonzero. */
1761 mpz_init (size);
1762 dynamic = gfc_get_array_constructor_size (&size, c);
1763 mpz_sub_ui (size, size, 1);
1764 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1765 mpz_clear (size);
1768 /* Special case constant array constructors. */
1769 if (!dynamic)
1771 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
1772 if (nelem > 0)
1774 tree size = constant_array_constructor_loop_size (loop);
1775 if (size && compare_tree_int (size, nelem) == 0)
1777 gfc_trans_constant_array_constructor (loop, ss, type);
1778 return;
1783 /* Temporarily reset the loop variables, so that the returned temporary
1784 has the right size and bounds. This seems only to be necessary for
1785 1D arrays. */
1786 if (!integer_zerop (loop->from[0]) && loop->dimen == 1)
1788 loopfrom = loop->from[0];
1789 loop->from[0] = gfc_index_zero_node;
1790 loop->to[0] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1791 loop->to[0], loopfrom);
1793 else
1794 loopfrom = NULL_TREE;
1796 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
1797 type, dynamic, true, false);
1799 if (loopfrom != NULL_TREE)
1801 loop->from[0] = loopfrom;
1802 loop->to[0] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1803 loop->to[0], loopfrom);
1804 /* In the case of a non-zero from, the temporary needs an offset
1805 so that subsequent indexing is correct. */
1806 ss->data.info.offset = fold_build1 (NEGATE_EXPR,
1807 gfc_array_index_type,
1808 loop->from[0]);
1811 desc = ss->data.info.descriptor;
1812 offset = gfc_index_zero_node;
1813 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1814 TREE_NO_WARNING (offsetvar) = 1;
1815 TREE_USED (offsetvar) = 0;
1816 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
1817 &offset, &offsetvar, dynamic);
1819 /* If the array grows dynamically, the upper bound of the loop variable
1820 is determined by the array's final upper bound. */
1821 if (dynamic)
1822 loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
1824 if (TREE_USED (offsetvar))
1825 pushdecl (offsetvar);
1826 else
1827 gcc_assert (INTEGER_CST_P (offset));
1828 #if 0
1829 /* Disable bound checking for now because it's probably broken. */
1830 if (flag_bounds_check)
1832 gcc_unreachable ();
1834 #endif
1838 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
1839 called after evaluating all of INFO's vector dimensions. Go through
1840 each such vector dimension and see if we can now fill in any missing
1841 loop bounds. */
1843 static void
1844 gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
1846 gfc_se se;
1847 tree tmp;
1848 tree desc;
1849 tree zero;
1850 int n;
1851 int dim;
1853 for (n = 0; n < loop->dimen; n++)
1855 dim = info->dim[n];
1856 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
1857 && loop->to[n] == NULL)
1859 /* Loop variable N indexes vector dimension DIM, and we don't
1860 yet know the upper bound of loop variable N. Set it to the
1861 difference between the vector's upper and lower bounds. */
1862 gcc_assert (loop->from[n] == gfc_index_zero_node);
1863 gcc_assert (info->subscript[dim]
1864 && info->subscript[dim]->type == GFC_SS_VECTOR);
1866 gfc_init_se (&se, NULL);
1867 desc = info->subscript[dim]->data.info.descriptor;
1868 zero = gfc_rank_cst[0];
1869 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1870 gfc_conv_descriptor_ubound (desc, zero),
1871 gfc_conv_descriptor_lbound (desc, zero));
1872 tmp = gfc_evaluate_now (tmp, &loop->pre);
1873 loop->to[n] = tmp;
1879 /* Add the pre and post chains for all the scalar expressions in a SS chain
1880 to loop. This is called after the loop parameters have been calculated,
1881 but before the actual scalarizing loops. */
1883 static void
1884 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript)
1886 gfc_se se;
1887 int n;
1889 /* TODO: This can generate bad code if there are ordering dependencies.
1890 eg. a callee allocated function and an unknown size constructor. */
1891 gcc_assert (ss != NULL);
1893 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
1895 gcc_assert (ss);
1897 switch (ss->type)
1899 case GFC_SS_SCALAR:
1900 /* Scalar expression. Evaluate this now. This includes elemental
1901 dimension indices, but not array section bounds. */
1902 gfc_init_se (&se, NULL);
1903 gfc_conv_expr (&se, ss->expr);
1904 gfc_add_block_to_block (&loop->pre, &se.pre);
1906 if (ss->expr->ts.type != BT_CHARACTER)
1908 /* Move the evaluation of scalar expressions outside the
1909 scalarization loop, except for WHERE assignments. */
1910 if (subscript)
1911 se.expr = convert(gfc_array_index_type, se.expr);
1912 if (!ss->where)
1913 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
1914 gfc_add_block_to_block (&loop->pre, &se.post);
1916 else
1917 gfc_add_block_to_block (&loop->post, &se.post);
1919 ss->data.scalar.expr = se.expr;
1920 ss->string_length = se.string_length;
1921 break;
1923 case GFC_SS_REFERENCE:
1924 /* Scalar reference. Evaluate this now. */
1925 gfc_init_se (&se, NULL);
1926 gfc_conv_expr_reference (&se, ss->expr);
1927 gfc_add_block_to_block (&loop->pre, &se.pre);
1928 gfc_add_block_to_block (&loop->post, &se.post);
1930 ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
1931 ss->string_length = se.string_length;
1932 break;
1934 case GFC_SS_SECTION:
1935 /* Add the expressions for scalar and vector subscripts. */
1936 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1937 if (ss->data.info.subscript[n])
1938 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true);
1940 gfc_set_vector_loop_bounds (loop, &ss->data.info);
1941 break;
1943 case GFC_SS_VECTOR:
1944 /* Get the vector's descriptor and store it in SS. */
1945 gfc_init_se (&se, NULL);
1946 gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
1947 gfc_add_block_to_block (&loop->pre, &se.pre);
1948 gfc_add_block_to_block (&loop->post, &se.post);
1949 ss->data.info.descriptor = se.expr;
1950 break;
1952 case GFC_SS_INTRINSIC:
1953 gfc_add_intrinsic_ss_code (loop, ss);
1954 break;
1956 case GFC_SS_FUNCTION:
1957 /* Array function return value. We call the function and save its
1958 result in a temporary for use inside the loop. */
1959 gfc_init_se (&se, NULL);
1960 se.loop = loop;
1961 se.ss = ss;
1962 gfc_conv_expr (&se, ss->expr);
1963 gfc_add_block_to_block (&loop->pre, &se.pre);
1964 gfc_add_block_to_block (&loop->post, &se.post);
1965 ss->string_length = se.string_length;
1966 break;
1968 case GFC_SS_CONSTRUCTOR:
1969 if (ss->expr->ts.type == BT_CHARACTER
1970 && ss->string_length == NULL
1971 && ss->expr->ts.cl
1972 && ss->expr->ts.cl->length)
1974 gfc_init_se (&se, NULL);
1975 gfc_conv_expr_type (&se, ss->expr->ts.cl->length,
1976 gfc_charlen_type_node);
1977 ss->string_length = se.expr;
1978 gfc_add_block_to_block (&loop->pre, &se.pre);
1979 gfc_add_block_to_block (&loop->post, &se.post);
1981 gfc_trans_array_constructor (loop, ss);
1982 break;
1984 case GFC_SS_TEMP:
1985 case GFC_SS_COMPONENT:
1986 /* Do nothing. These are handled elsewhere. */
1987 break;
1989 default:
1990 gcc_unreachable ();
1996 /* Translate expressions for the descriptor and data pointer of a SS. */
1997 /*GCC ARRAYS*/
1999 static void
2000 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2002 gfc_se se;
2003 tree tmp;
2005 /* Get the descriptor for the array to be scalarized. */
2006 gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
2007 gfc_init_se (&se, NULL);
2008 se.descriptor_only = 1;
2009 gfc_conv_expr_lhs (&se, ss->expr);
2010 gfc_add_block_to_block (block, &se.pre);
2011 ss->data.info.descriptor = se.expr;
2012 ss->string_length = se.string_length;
2014 if (base)
2016 /* Also the data pointer. */
2017 tmp = gfc_conv_array_data (se.expr);
2018 /* If this is a variable or address of a variable we use it directly.
2019 Otherwise we must evaluate it now to avoid breaking dependency
2020 analysis by pulling the expressions for elemental array indices
2021 inside the loop. */
2022 if (!(DECL_P (tmp)
2023 || (TREE_CODE (tmp) == ADDR_EXPR
2024 && DECL_P (TREE_OPERAND (tmp, 0)))))
2025 tmp = gfc_evaluate_now (tmp, block);
2026 ss->data.info.data = tmp;
2028 tmp = gfc_conv_array_offset (se.expr);
2029 ss->data.info.offset = gfc_evaluate_now (tmp, block);
2034 /* Initialize a gfc_loopinfo structure. */
2036 void
2037 gfc_init_loopinfo (gfc_loopinfo * loop)
2039 int n;
2041 memset (loop, 0, sizeof (gfc_loopinfo));
2042 gfc_init_block (&loop->pre);
2043 gfc_init_block (&loop->post);
2045 /* Initially scalarize in order. */
2046 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2047 loop->order[n] = n;
2049 loop->ss = gfc_ss_terminator;
2053 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2054 chain. */
2056 void
2057 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2059 se->loop = loop;
2063 /* Return an expression for the data pointer of an array. */
2065 tree
2066 gfc_conv_array_data (tree descriptor)
2068 tree type;
2070 type = TREE_TYPE (descriptor);
2071 if (GFC_ARRAY_TYPE_P (type))
2073 if (TREE_CODE (type) == POINTER_TYPE)
2074 return descriptor;
2075 else
2077 /* Descriptorless arrays. */
2078 return build_fold_addr_expr (descriptor);
2081 else
2082 return gfc_conv_descriptor_data_get (descriptor);
2086 /* Return an expression for the base offset of an array. */
2088 tree
2089 gfc_conv_array_offset (tree descriptor)
2091 tree type;
2093 type = TREE_TYPE (descriptor);
2094 if (GFC_ARRAY_TYPE_P (type))
2095 return GFC_TYPE_ARRAY_OFFSET (type);
2096 else
2097 return gfc_conv_descriptor_offset (descriptor);
2101 /* Get an expression for the array stride. */
2103 tree
2104 gfc_conv_array_stride (tree descriptor, int dim)
2106 tree tmp;
2107 tree type;
2109 type = TREE_TYPE (descriptor);
2111 /* For descriptorless arrays use the array size. */
2112 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2113 if (tmp != NULL_TREE)
2114 return tmp;
2116 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
2117 return tmp;
2121 /* Like gfc_conv_array_stride, but for the lower bound. */
2123 tree
2124 gfc_conv_array_lbound (tree descriptor, int dim)
2126 tree tmp;
2127 tree type;
2129 type = TREE_TYPE (descriptor);
2131 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2132 if (tmp != NULL_TREE)
2133 return tmp;
2135 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
2136 return tmp;
2140 /* Like gfc_conv_array_stride, but for the upper bound. */
2142 tree
2143 gfc_conv_array_ubound (tree descriptor, int dim)
2145 tree tmp;
2146 tree type;
2148 type = TREE_TYPE (descriptor);
2150 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2151 if (tmp != NULL_TREE)
2152 return tmp;
2154 /* This should only ever happen when passing an assumed shape array
2155 as an actual parameter. The value will never be used. */
2156 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2157 return gfc_index_zero_node;
2159 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
2160 return tmp;
2164 /* Generate code to perform an array index bound check. */
2166 static tree
2167 gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
2168 locus * where, bool check_upper)
2170 tree fault;
2171 tree tmp;
2172 char *msg;
2173 const char * name = NULL;
2175 if (!flag_bounds_check)
2176 return index;
2178 index = gfc_evaluate_now (index, &se->pre);
2180 /* We find a name for the error message. */
2181 if (se->ss)
2182 name = se->ss->expr->symtree->name;
2184 if (!name && se->loop && se->loop->ss && se->loop->ss->expr
2185 && se->loop->ss->expr->symtree)
2186 name = se->loop->ss->expr->symtree->name;
2188 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2189 && se->loop->ss->loop_chain->expr
2190 && se->loop->ss->loop_chain->expr->symtree)
2191 name = se->loop->ss->loop_chain->expr->symtree->name;
2193 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2194 && se->loop->ss->loop_chain->expr->symtree)
2195 name = se->loop->ss->loop_chain->expr->symtree->name;
2197 if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
2199 if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
2200 && se->loop->ss->expr->value.function.name)
2201 name = se->loop->ss->expr->value.function.name;
2202 else
2203 if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
2204 || se->loop->ss->type == GFC_SS_SCALAR)
2205 name = "unnamed constant";
2208 /* Check lower bound. */
2209 tmp = gfc_conv_array_lbound (descriptor, n);
2210 fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
2211 if (name)
2212 asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
2213 "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
2214 else
2215 asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
2216 gfc_msg_fault, n+1);
2217 gfc_trans_runtime_check (fault, &se->pre, where, msg,
2218 fold_convert (long_integer_type_node, index),
2219 fold_convert (long_integer_type_node, tmp));
2220 gfc_free (msg);
2222 /* Check upper bound. */
2223 if (check_upper)
2225 tmp = gfc_conv_array_ubound (descriptor, n);
2226 fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
2227 if (name)
2228 asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
2229 " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
2230 else
2231 asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
2232 gfc_msg_fault, n+1);
2233 gfc_trans_runtime_check (fault, &se->pre, where, msg,
2234 fold_convert (long_integer_type_node, index),
2235 fold_convert (long_integer_type_node, tmp));
2236 gfc_free (msg);
2239 return index;
2243 /* Return the offset for an index. Performs bound checking for elemental
2244 dimensions. Single element references are processed separately. */
2246 static tree
2247 gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
2248 gfc_array_ref * ar, tree stride)
2250 tree index;
2251 tree desc;
2252 tree data;
2254 /* Get the index into the array for this dimension. */
2255 if (ar)
2257 gcc_assert (ar->type != AR_ELEMENT);
2258 switch (ar->dimen_type[dim])
2260 case DIMEN_ELEMENT:
2261 /* Elemental dimension. */
2262 gcc_assert (info->subscript[dim]
2263 && info->subscript[dim]->type == GFC_SS_SCALAR);
2264 /* We've already translated this value outside the loop. */
2265 index = info->subscript[dim]->data.scalar.expr;
2267 index = gfc_trans_array_bound_check (se, info->descriptor,
2268 index, dim, &ar->where,
2269 (ar->as->type != AS_ASSUMED_SIZE
2270 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2271 break;
2273 case DIMEN_VECTOR:
2274 gcc_assert (info && se->loop);
2275 gcc_assert (info->subscript[dim]
2276 && info->subscript[dim]->type == GFC_SS_VECTOR);
2277 desc = info->subscript[dim]->data.info.descriptor;
2279 /* Get a zero-based index into the vector. */
2280 index = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2281 se->loop->loopvar[i], se->loop->from[i]);
2283 /* Multiply the index by the stride. */
2284 index = fold_build2 (MULT_EXPR, gfc_array_index_type,
2285 index, gfc_conv_array_stride (desc, 0));
2287 /* Read the vector to get an index into info->descriptor. */
2288 data = build_fold_indirect_ref (gfc_conv_array_data (desc));
2289 index = gfc_build_array_ref (data, index, NULL);
2290 index = gfc_evaluate_now (index, &se->pre);
2292 /* Do any bounds checking on the final info->descriptor index. */
2293 index = gfc_trans_array_bound_check (se, info->descriptor,
2294 index, dim, &ar->where,
2295 (ar->as->type != AS_ASSUMED_SIZE
2296 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2297 break;
2299 case DIMEN_RANGE:
2300 /* Scalarized dimension. */
2301 gcc_assert (info && se->loop);
2303 /* Multiply the loop variable by the stride and delta. */
2304 index = se->loop->loopvar[i];
2305 if (!integer_onep (info->stride[i]))
2306 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index,
2307 info->stride[i]);
2308 if (!integer_zerop (info->delta[i]))
2309 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index,
2310 info->delta[i]);
2311 break;
2313 default:
2314 gcc_unreachable ();
2317 else
2319 /* Temporary array or derived type component. */
2320 gcc_assert (se->loop);
2321 index = se->loop->loopvar[se->loop->order[i]];
2322 if (!integer_zerop (info->delta[i]))
2323 index = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2324 index, info->delta[i]);
2327 /* Multiply by the stride. */
2328 if (!integer_onep (stride))
2329 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index, stride);
2331 return index;
2335 /* Build a scalarized reference to an array. */
2337 static void
2338 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2340 gfc_ss_info *info;
2341 tree decl = NULL_TREE;
2342 tree index;
2343 tree tmp;
2344 int n;
2346 info = &se->ss->data.info;
2347 if (ar)
2348 n = se->loop->order[0];
2349 else
2350 n = 0;
2352 index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
2353 info->stride0);
2354 /* Add the offset for this dimension to the stored offset for all other
2355 dimensions. */
2356 if (!integer_zerop (info->offset))
2357 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset);
2359 if (se->ss->expr && is_subref_array (se->ss->expr))
2360 decl = se->ss->expr->symtree->n.sym->backend_decl;
2362 tmp = build_fold_indirect_ref (info->data);
2363 se->expr = gfc_build_array_ref (tmp, index, decl);
2367 /* Translate access of temporary array. */
2369 void
2370 gfc_conv_tmp_array_ref (gfc_se * se)
2372 se->string_length = se->ss->string_length;
2373 gfc_conv_scalarized_array_ref (se, NULL);
2377 /* Build an array reference. se->expr already holds the array descriptor.
2378 This should be either a variable, indirect variable reference or component
2379 reference. For arrays which do not have a descriptor, se->expr will be
2380 the data pointer.
2381 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2383 void
2384 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2385 locus * where)
2387 int n;
2388 tree index;
2389 tree tmp;
2390 tree stride;
2391 gfc_se indexse;
2393 /* Handle scalarized references separately. */
2394 if (ar->type != AR_ELEMENT)
2396 gfc_conv_scalarized_array_ref (se, ar);
2397 gfc_advance_se_ss_chain (se);
2398 return;
2401 index = gfc_index_zero_node;
2403 /* Calculate the offsets from all the dimensions. */
2404 for (n = 0; n < ar->dimen; n++)
2406 /* Calculate the index for this dimension. */
2407 gfc_init_se (&indexse, se);
2408 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2409 gfc_add_block_to_block (&se->pre, &indexse.pre);
2411 if (flag_bounds_check)
2413 /* Check array bounds. */
2414 tree cond;
2415 char *msg;
2417 /* Evaluate the indexse.expr only once. */
2418 indexse.expr = save_expr (indexse.expr);
2420 /* Lower bound. */
2421 tmp = gfc_conv_array_lbound (se->expr, n);
2422 cond = fold_build2 (LT_EXPR, boolean_type_node,
2423 indexse.expr, tmp);
2424 asprintf (&msg, "%s for array '%s', "
2425 "lower bound of dimension %d exceeded (%%ld < %%ld)",
2426 gfc_msg_fault, sym->name, n+1);
2427 gfc_trans_runtime_check (cond, &se->pre, where, msg,
2428 fold_convert (long_integer_type_node,
2429 indexse.expr),
2430 fold_convert (long_integer_type_node, tmp));
2431 gfc_free (msg);
2433 /* Upper bound, but not for the last dimension of assumed-size
2434 arrays. */
2435 if (n < ar->dimen - 1
2436 || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
2438 tmp = gfc_conv_array_ubound (se->expr, n);
2439 cond = fold_build2 (GT_EXPR, boolean_type_node,
2440 indexse.expr, tmp);
2441 asprintf (&msg, "%s for array '%s', "
2442 "upper bound of dimension %d exceeded (%%ld > %%ld)",
2443 gfc_msg_fault, sym->name, n+1);
2444 gfc_trans_runtime_check (cond, &se->pre, where, msg,
2445 fold_convert (long_integer_type_node,
2446 indexse.expr),
2447 fold_convert (long_integer_type_node, tmp));
2448 gfc_free (msg);
2452 /* Multiply the index by the stride. */
2453 stride = gfc_conv_array_stride (se->expr, n);
2454 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
2455 stride);
2457 /* And add it to the total. */
2458 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2461 tmp = gfc_conv_array_offset (se->expr);
2462 if (!integer_zerop (tmp))
2463 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2465 /* Access the calculated element. */
2466 tmp = gfc_conv_array_data (se->expr);
2467 tmp = build_fold_indirect_ref (tmp);
2468 se->expr = gfc_build_array_ref (tmp, index, sym->backend_decl);
2472 /* Generate the code to be executed immediately before entering a
2473 scalarization loop. */
2475 static void
2476 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2477 stmtblock_t * pblock)
2479 tree index;
2480 tree stride;
2481 gfc_ss_info *info;
2482 gfc_ss *ss;
2483 gfc_se se;
2484 int i;
2486 /* This code will be executed before entering the scalarization loop
2487 for this dimension. */
2488 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2490 if ((ss->useflags & flag) == 0)
2491 continue;
2493 if (ss->type != GFC_SS_SECTION
2494 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2495 && ss->type != GFC_SS_COMPONENT)
2496 continue;
2498 info = &ss->data.info;
2500 if (dim >= info->dimen)
2501 continue;
2503 if (dim == info->dimen - 1)
2505 /* For the outermost loop calculate the offset due to any
2506 elemental dimensions. It will have been initialized with the
2507 base offset of the array. */
2508 if (info->ref)
2510 for (i = 0; i < info->ref->u.ar.dimen; i++)
2512 if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2513 continue;
2515 gfc_init_se (&se, NULL);
2516 se.loop = loop;
2517 se.expr = info->descriptor;
2518 stride = gfc_conv_array_stride (info->descriptor, i);
2519 index = gfc_conv_array_index_offset (&se, info, i, -1,
2520 &info->ref->u.ar,
2521 stride);
2522 gfc_add_block_to_block (pblock, &se.pre);
2524 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2525 info->offset, index);
2526 info->offset = gfc_evaluate_now (info->offset, pblock);
2529 i = loop->order[0];
2530 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2532 else
2533 stride = gfc_conv_array_stride (info->descriptor, 0);
2535 /* Calculate the stride of the innermost loop. Hopefully this will
2536 allow the backend optimizers to do their stuff more effectively.
2538 info->stride0 = gfc_evaluate_now (stride, pblock);
2540 else
2542 /* Add the offset for the previous loop dimension. */
2543 gfc_array_ref *ar;
2545 if (info->ref)
2547 ar = &info->ref->u.ar;
2548 i = loop->order[dim + 1];
2550 else
2552 ar = NULL;
2553 i = dim + 1;
2556 gfc_init_se (&se, NULL);
2557 se.loop = loop;
2558 se.expr = info->descriptor;
2559 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2560 index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
2561 ar, stride);
2562 gfc_add_block_to_block (pblock, &se.pre);
2563 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2564 info->offset, index);
2565 info->offset = gfc_evaluate_now (info->offset, pblock);
2568 /* Remember this offset for the second loop. */
2569 if (dim == loop->temp_dim - 1)
2570 info->saved_offset = info->offset;
2575 /* Start a scalarized expression. Creates a scope and declares loop
2576 variables. */
2578 void
2579 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2581 int dim;
2582 int n;
2583 int flags;
2585 gcc_assert (!loop->array_parameter);
2587 for (dim = loop->dimen - 1; dim >= 0; dim--)
2589 n = loop->order[dim];
2591 gfc_start_block (&loop->code[n]);
2593 /* Create the loop variable. */
2594 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2596 if (dim < loop->temp_dim)
2597 flags = 3;
2598 else
2599 flags = 1;
2600 /* Calculate values that will be constant within this loop. */
2601 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
2603 gfc_start_block (pbody);
2607 /* Generates the actual loop code for a scalarization loop. */
2609 static void
2610 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
2611 stmtblock_t * pbody)
2613 stmtblock_t block;
2614 tree cond;
2615 tree tmp;
2616 tree loopbody;
2617 tree exit_label;
2619 loopbody = gfc_finish_block (pbody);
2621 /* Initialize the loopvar. */
2622 gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]);
2624 exit_label = gfc_build_label_decl (NULL_TREE);
2626 /* Generate the loop body. */
2627 gfc_init_block (&block);
2629 /* The exit condition. */
2630 cond = fold_build2 (GT_EXPR, boolean_type_node,
2631 loop->loopvar[n], loop->to[n]);
2632 tmp = build1_v (GOTO_EXPR, exit_label);
2633 TREE_USED (exit_label) = 1;
2634 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
2635 gfc_add_expr_to_block (&block, tmp);
2637 /* The main body. */
2638 gfc_add_expr_to_block (&block, loopbody);
2640 /* Increment the loopvar. */
2641 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2642 loop->loopvar[n], gfc_index_one_node);
2643 gfc_add_modify_expr (&block, loop->loopvar[n], tmp);
2645 /* Build the loop. */
2646 tmp = gfc_finish_block (&block);
2647 tmp = build1_v (LOOP_EXPR, tmp);
2648 gfc_add_expr_to_block (&loop->code[n], tmp);
2650 /* Add the exit label. */
2651 tmp = build1_v (LABEL_EXPR, exit_label);
2652 gfc_add_expr_to_block (&loop->code[n], tmp);
2656 /* Finishes and generates the loops for a scalarized expression. */
2658 void
2659 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
2661 int dim;
2662 int n;
2663 gfc_ss *ss;
2664 stmtblock_t *pblock;
2665 tree tmp;
2667 pblock = body;
2668 /* Generate the loops. */
2669 for (dim = 0; dim < loop->dimen; dim++)
2671 n = loop->order[dim];
2672 gfc_trans_scalarized_loop_end (loop, n, pblock);
2673 loop->loopvar[n] = NULL_TREE;
2674 pblock = &loop->code[n];
2677 tmp = gfc_finish_block (pblock);
2678 gfc_add_expr_to_block (&loop->pre, tmp);
2680 /* Clear all the used flags. */
2681 for (ss = loop->ss; ss; ss = ss->loop_chain)
2682 ss->useflags = 0;
2686 /* Finish the main body of a scalarized expression, and start the secondary
2687 copying body. */
2689 void
2690 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
2692 int dim;
2693 int n;
2694 stmtblock_t *pblock;
2695 gfc_ss *ss;
2697 pblock = body;
2698 /* We finish as many loops as are used by the temporary. */
2699 for (dim = 0; dim < loop->temp_dim - 1; dim++)
2701 n = loop->order[dim];
2702 gfc_trans_scalarized_loop_end (loop, n, pblock);
2703 loop->loopvar[n] = NULL_TREE;
2704 pblock = &loop->code[n];
2707 /* We don't want to finish the outermost loop entirely. */
2708 n = loop->order[loop->temp_dim - 1];
2709 gfc_trans_scalarized_loop_end (loop, n, pblock);
2711 /* Restore the initial offsets. */
2712 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2714 if ((ss->useflags & 2) == 0)
2715 continue;
2717 if (ss->type != GFC_SS_SECTION
2718 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2719 && ss->type != GFC_SS_COMPONENT)
2720 continue;
2722 ss->data.info.offset = ss->data.info.saved_offset;
2725 /* Restart all the inner loops we just finished. */
2726 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
2728 n = loop->order[dim];
2730 gfc_start_block (&loop->code[n]);
2732 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
2734 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
2737 /* Start a block for the secondary copying code. */
2738 gfc_start_block (body);
2742 /* Calculate the upper bound of an array section. */
2744 static tree
2745 gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
2747 int dim;
2748 gfc_expr *end;
2749 tree desc;
2750 tree bound;
2751 gfc_se se;
2752 gfc_ss_info *info;
2754 gcc_assert (ss->type == GFC_SS_SECTION);
2756 info = &ss->data.info;
2757 dim = info->dim[n];
2759 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2760 /* We'll calculate the upper bound once we have access to the
2761 vector's descriptor. */
2762 return NULL;
2764 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2765 desc = info->descriptor;
2766 end = info->ref->u.ar.end[dim];
2768 if (end)
2770 /* The upper bound was specified. */
2771 gfc_init_se (&se, NULL);
2772 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2773 gfc_add_block_to_block (pblock, &se.pre);
2774 bound = se.expr;
2776 else
2778 /* No upper bound was specified, so use the bound of the array. */
2779 bound = gfc_conv_array_ubound (desc, dim);
2782 return bound;
2786 /* Calculate the lower bound of an array section. */
2788 static void
2789 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
2791 gfc_expr *start;
2792 gfc_expr *end;
2793 gfc_expr *stride;
2794 tree desc;
2795 gfc_se se;
2796 gfc_ss_info *info;
2797 int dim;
2799 gcc_assert (ss->type == GFC_SS_SECTION);
2801 info = &ss->data.info;
2802 dim = info->dim[n];
2804 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2806 /* We use a zero-based index to access the vector. */
2807 info->start[n] = gfc_index_zero_node;
2808 info->end[n] = gfc_index_zero_node;
2809 info->stride[n] = gfc_index_one_node;
2810 return;
2813 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2814 desc = info->descriptor;
2815 start = info->ref->u.ar.start[dim];
2816 end = info->ref->u.ar.end[dim];
2817 stride = info->ref->u.ar.stride[dim];
2819 /* Calculate the start of the range. For vector subscripts this will
2820 be the range of the vector. */
2821 if (start)
2823 /* Specified section start. */
2824 gfc_init_se (&se, NULL);
2825 gfc_conv_expr_type (&se, start, gfc_array_index_type);
2826 gfc_add_block_to_block (&loop->pre, &se.pre);
2827 info->start[n] = se.expr;
2829 else
2831 /* No lower bound specified so use the bound of the array. */
2832 info->start[n] = gfc_conv_array_lbound (desc, dim);
2834 info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
2836 /* Similarly calculate the end. Although this is not used in the
2837 scalarizer, it is needed when checking bounds and where the end
2838 is an expression with side-effects. */
2839 if (end)
2841 /* Specified section start. */
2842 gfc_init_se (&se, NULL);
2843 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2844 gfc_add_block_to_block (&loop->pre, &se.pre);
2845 info->end[n] = se.expr;
2847 else
2849 /* No upper bound specified so use the bound of the array. */
2850 info->end[n] = gfc_conv_array_ubound (desc, dim);
2852 info->end[n] = gfc_evaluate_now (info->end[n], &loop->pre);
2854 /* Calculate the stride. */
2855 if (stride == NULL)
2856 info->stride[n] = gfc_index_one_node;
2857 else
2859 gfc_init_se (&se, NULL);
2860 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
2861 gfc_add_block_to_block (&loop->pre, &se.pre);
2862 info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
2867 /* Calculates the range start and stride for a SS chain. Also gets the
2868 descriptor and data pointer. The range of vector subscripts is the size
2869 of the vector. Array bounds are also checked. */
2871 void
2872 gfc_conv_ss_startstride (gfc_loopinfo * loop)
2874 int n;
2875 tree tmp;
2876 gfc_ss *ss;
2877 tree desc;
2879 loop->dimen = 0;
2880 /* Determine the rank of the loop. */
2881 for (ss = loop->ss;
2882 ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
2884 switch (ss->type)
2886 case GFC_SS_SECTION:
2887 case GFC_SS_CONSTRUCTOR:
2888 case GFC_SS_FUNCTION:
2889 case GFC_SS_COMPONENT:
2890 loop->dimen = ss->data.info.dimen;
2891 break;
2893 /* As usual, lbound and ubound are exceptions!. */
2894 case GFC_SS_INTRINSIC:
2895 switch (ss->expr->value.function.isym->id)
2897 case GFC_ISYM_LBOUND:
2898 case GFC_ISYM_UBOUND:
2899 loop->dimen = ss->data.info.dimen;
2901 default:
2902 break;
2905 default:
2906 break;
2910 /* We should have determined the rank of the expression by now. If
2911 not, that's bad news. */
2912 gcc_assert (loop->dimen != 0);
2914 /* Loop over all the SS in the chain. */
2915 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2917 if (ss->expr && ss->expr->shape && !ss->shape)
2918 ss->shape = ss->expr->shape;
2920 switch (ss->type)
2922 case GFC_SS_SECTION:
2923 /* Get the descriptor for the array. */
2924 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
2926 for (n = 0; n < ss->data.info.dimen; n++)
2927 gfc_conv_section_startstride (loop, ss, n);
2928 break;
2930 case GFC_SS_INTRINSIC:
2931 switch (ss->expr->value.function.isym->id)
2933 /* Fall through to supply start and stride. */
2934 case GFC_ISYM_LBOUND:
2935 case GFC_ISYM_UBOUND:
2936 break;
2937 default:
2938 continue;
2941 case GFC_SS_CONSTRUCTOR:
2942 case GFC_SS_FUNCTION:
2943 for (n = 0; n < ss->data.info.dimen; n++)
2945 ss->data.info.start[n] = gfc_index_zero_node;
2946 ss->data.info.end[n] = gfc_index_zero_node;
2947 ss->data.info.stride[n] = gfc_index_one_node;
2949 break;
2951 default:
2952 break;
2956 /* The rest is just runtime bound checking. */
2957 if (flag_bounds_check)
2959 stmtblock_t block;
2960 tree lbound, ubound;
2961 tree end;
2962 tree size[GFC_MAX_DIMENSIONS];
2963 tree stride_pos, stride_neg, non_zerosized, tmp2;
2964 gfc_ss_info *info;
2965 char *msg;
2966 int dim;
2968 gfc_start_block (&block);
2970 for (n = 0; n < loop->dimen; n++)
2971 size[n] = NULL_TREE;
2973 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2975 stmtblock_t inner;
2977 if (ss->type != GFC_SS_SECTION)
2978 continue;
2980 gfc_start_block (&inner);
2982 /* TODO: range checking for mapped dimensions. */
2983 info = &ss->data.info;
2985 /* This code only checks ranges. Elemental and vector
2986 dimensions are checked later. */
2987 for (n = 0; n < loop->dimen; n++)
2989 bool check_upper;
2991 dim = info->dim[n];
2992 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
2993 continue;
2995 if (dim == info->ref->u.ar.dimen - 1
2996 && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
2997 || info->ref->u.ar.as->cp_was_assumed))
2998 check_upper = false;
2999 else
3000 check_upper = true;
3002 /* Zero stride is not allowed. */
3003 tmp = fold_build2 (EQ_EXPR, boolean_type_node, info->stride[n],
3004 gfc_index_zero_node);
3005 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
3006 "of array '%s'", info->dim[n]+1,
3007 ss->expr->symtree->name);
3008 gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg);
3009 gfc_free (msg);
3011 desc = ss->data.info.descriptor;
3013 /* This is the run-time equivalent of resolve.c's
3014 check_dimension(). The logical is more readable there
3015 than it is here, with all the trees. */
3016 lbound = gfc_conv_array_lbound (desc, dim);
3017 end = info->end[n];
3018 if (check_upper)
3019 ubound = gfc_conv_array_ubound (desc, dim);
3020 else
3021 ubound = NULL;
3023 /* non_zerosized is true when the selected range is not
3024 empty. */
3025 stride_pos = fold_build2 (GT_EXPR, boolean_type_node,
3026 info->stride[n], gfc_index_zero_node);
3027 tmp = fold_build2 (LE_EXPR, boolean_type_node, info->start[n],
3028 end);
3029 stride_pos = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3030 stride_pos, tmp);
3032 stride_neg = fold_build2 (LT_EXPR, boolean_type_node,
3033 info->stride[n], gfc_index_zero_node);
3034 tmp = fold_build2 (GE_EXPR, boolean_type_node, info->start[n],
3035 end);
3036 stride_neg = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3037 stride_neg, tmp);
3038 non_zerosized = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
3039 stride_pos, stride_neg);
3041 /* Check the start of the range against the lower and upper
3042 bounds of the array, if the range is not empty. */
3043 tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
3044 lbound);
3045 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3046 non_zerosized, tmp);
3047 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
3048 " exceeded (%%ld < %%ld)", gfc_msg_fault,
3049 info->dim[n]+1, ss->expr->symtree->name);
3050 gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg,
3051 fold_convert (long_integer_type_node,
3052 info->start[n]),
3053 fold_convert (long_integer_type_node,
3054 lbound));
3055 gfc_free (msg);
3057 if (check_upper)
3059 tmp = fold_build2 (GT_EXPR, boolean_type_node,
3060 info->start[n], ubound);
3061 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3062 non_zerosized, tmp);
3063 asprintf (&msg, "%s, upper bound of dimension %d of array "
3064 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3065 info->dim[n]+1, ss->expr->symtree->name);
3066 gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg,
3067 fold_convert (long_integer_type_node, info->start[n]),
3068 fold_convert (long_integer_type_node, ubound));
3069 gfc_free (msg);
3072 /* Compute the last element of the range, which is not
3073 necessarily "end" (think 0:5:3, which doesn't contain 5)
3074 and check it against both lower and upper bounds. */
3075 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3076 info->start[n]);
3077 tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
3078 info->stride[n]);
3079 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3080 tmp2);
3082 tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
3083 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3084 non_zerosized, tmp);
3085 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
3086 " exceeded (%%ld < %%ld)", gfc_msg_fault,
3087 info->dim[n]+1, ss->expr->symtree->name);
3088 gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg,
3089 fold_convert (long_integer_type_node,
3090 tmp2),
3091 fold_convert (long_integer_type_node,
3092 lbound));
3093 gfc_free (msg);
3095 if (check_upper)
3097 tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
3098 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3099 non_zerosized, tmp);
3100 asprintf (&msg, "%s, upper bound of dimension %d of array "
3101 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3102 info->dim[n]+1, ss->expr->symtree->name);
3103 gfc_trans_runtime_check (tmp, &inner, &ss->expr->where, msg,
3104 fold_convert (long_integer_type_node, tmp2),
3105 fold_convert (long_integer_type_node, ubound));
3106 gfc_free (msg);
3109 /* Check the section sizes match. */
3110 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3111 info->start[n]);
3112 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
3113 info->stride[n]);
3114 tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
3115 build_int_cst (gfc_array_index_type, 0));
3116 /* We remember the size of the first section, and check all the
3117 others against this. */
3118 if (size[n])
3120 tree tmp3;
3122 tmp3 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
3123 asprintf (&msg, "%s, size mismatch for dimension %d "
3124 "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
3125 info->dim[n]+1, ss->expr->symtree->name);
3126 gfc_trans_runtime_check (tmp3, &inner, &ss->expr->where, msg,
3127 fold_convert (long_integer_type_node, tmp),
3128 fold_convert (long_integer_type_node, size[n]));
3129 gfc_free (msg);
3131 else
3132 size[n] = gfc_evaluate_now (tmp, &inner);
3135 tmp = gfc_finish_block (&inner);
3137 /* For optional arguments, only check bounds if the argument is
3138 present. */
3139 if (ss->expr->symtree->n.sym->attr.optional
3140 || ss->expr->symtree->n.sym->attr.not_always_present)
3141 tmp = build3_v (COND_EXPR,
3142 gfc_conv_expr_present (ss->expr->symtree->n.sym),
3143 tmp, build_empty_stmt ());
3145 gfc_add_expr_to_block (&block, tmp);
3149 tmp = gfc_finish_block (&block);
3150 gfc_add_expr_to_block (&loop->pre, tmp);
3155 /* Return true if the two SS could be aliased, i.e. both point to the same data
3156 object. */
3157 /* TODO: resolve aliases based on frontend expressions. */
3159 static int
3160 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
3162 gfc_ref *lref;
3163 gfc_ref *rref;
3164 gfc_symbol *lsym;
3165 gfc_symbol *rsym;
3167 lsym = lss->expr->symtree->n.sym;
3168 rsym = rss->expr->symtree->n.sym;
3169 if (gfc_symbols_could_alias (lsym, rsym))
3170 return 1;
3172 if (rsym->ts.type != BT_DERIVED
3173 && lsym->ts.type != BT_DERIVED)
3174 return 0;
3176 /* For derived types we must check all the component types. We can ignore
3177 array references as these will have the same base type as the previous
3178 component ref. */
3179 for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
3181 if (lref->type != REF_COMPONENT)
3182 continue;
3184 if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
3185 return 1;
3187 for (rref = rss->expr->ref; rref != rss->data.info.ref;
3188 rref = rref->next)
3190 if (rref->type != REF_COMPONENT)
3191 continue;
3193 if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
3194 return 1;
3198 for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
3200 if (rref->type != REF_COMPONENT)
3201 break;
3203 if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
3204 return 1;
3207 return 0;
3211 /* Resolve array data dependencies. Creates a temporary if required. */
3212 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
3213 dependency.c. */
3215 void
3216 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
3217 gfc_ss * rss)
3219 gfc_ss *ss;
3220 gfc_ref *lref;
3221 gfc_ref *rref;
3222 gfc_ref *aref;
3223 int nDepend = 0;
3224 int temp_dim = 0;
3226 loop->temp_ss = NULL;
3227 aref = dest->data.info.ref;
3228 temp_dim = 0;
3230 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
3232 if (ss->type != GFC_SS_SECTION)
3233 continue;
3235 if (gfc_could_be_alias (dest, ss)
3236 || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3238 nDepend = 1;
3239 break;
3242 if (dest->expr->symtree->n.sym == ss->expr->symtree->n.sym)
3244 lref = dest->expr->ref;
3245 rref = ss->expr->ref;
3247 nDepend = gfc_dep_resolver (lref, rref);
3248 if (nDepend == 1)
3249 break;
3250 #if 0
3251 /* TODO : loop shifting. */
3252 if (nDepend == 1)
3254 /* Mark the dimensions for LOOP SHIFTING */
3255 for (n = 0; n < loop->dimen; n++)
3257 int dim = dest->data.info.dim[n];
3259 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3260 depends[n] = 2;
3261 else if (! gfc_is_same_range (&lref->u.ar,
3262 &rref->u.ar, dim, 0))
3263 depends[n] = 1;
3266 /* Put all the dimensions with dependencies in the
3267 innermost loops. */
3268 dim = 0;
3269 for (n = 0; n < loop->dimen; n++)
3271 gcc_assert (loop->order[n] == n);
3272 if (depends[n])
3273 loop->order[dim++] = n;
3275 temp_dim = dim;
3276 for (n = 0; n < loop->dimen; n++)
3278 if (! depends[n])
3279 loop->order[dim++] = n;
3282 gcc_assert (dim == loop->dimen);
3283 break;
3285 #endif
3289 if (nDepend == 1)
3291 tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
3292 if (GFC_ARRAY_TYPE_P (base_type)
3293 || GFC_DESCRIPTOR_TYPE_P (base_type))
3294 base_type = gfc_get_element_type (base_type);
3295 loop->temp_ss = gfc_get_ss ();
3296 loop->temp_ss->type = GFC_SS_TEMP;
3297 loop->temp_ss->data.temp.type = base_type;
3298 loop->temp_ss->string_length = dest->string_length;
3299 loop->temp_ss->data.temp.dimen = loop->dimen;
3300 loop->temp_ss->next = gfc_ss_terminator;
3301 gfc_add_ss_to_loop (loop, loop->temp_ss);
3303 else
3304 loop->temp_ss = NULL;
3308 /* Initialize the scalarization loop. Creates the loop variables. Determines
3309 the range of the loop variables. Creates a temporary if required.
3310 Calculates how to transform from loop variables to array indices for each
3311 expression. Also generates code for scalar expressions which have been
3312 moved outside the loop. */
3314 void
3315 gfc_conv_loop_setup (gfc_loopinfo * loop)
3317 int n;
3318 int dim;
3319 gfc_ss_info *info;
3320 gfc_ss_info *specinfo;
3321 gfc_ss *ss;
3322 tree tmp;
3323 tree len;
3324 gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
3325 bool dynamic[GFC_MAX_DIMENSIONS];
3326 gfc_constructor *c;
3327 mpz_t *cshape;
3328 mpz_t i;
3330 mpz_init (i);
3331 for (n = 0; n < loop->dimen; n++)
3333 loopspec[n] = NULL;
3334 dynamic[n] = false;
3335 /* We use one SS term, and use that to determine the bounds of the
3336 loop for this dimension. We try to pick the simplest term. */
3337 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3339 if (ss->shape)
3341 /* The frontend has worked out the size for us. */
3342 loopspec[n] = ss;
3343 continue;
3346 if (ss->type == GFC_SS_CONSTRUCTOR)
3348 /* An unknown size constructor will always be rank one.
3349 Higher rank constructors will either have known shape,
3350 or still be wrapped in a call to reshape. */
3351 gcc_assert (loop->dimen == 1);
3353 /* Always prefer to use the constructor bounds if the size
3354 can be determined at compile time. Prefer not to otherwise,
3355 since the general case involves realloc, and it's better to
3356 avoid that overhead if possible. */
3357 c = ss->expr->value.constructor;
3358 dynamic[n] = gfc_get_array_constructor_size (&i, c);
3359 if (!dynamic[n] || !loopspec[n])
3360 loopspec[n] = ss;
3361 continue;
3364 /* TODO: Pick the best bound if we have a choice between a
3365 function and something else. */
3366 if (ss->type == GFC_SS_FUNCTION)
3368 loopspec[n] = ss;
3369 continue;
3372 if (ss->type != GFC_SS_SECTION)
3373 continue;
3375 if (loopspec[n])
3376 specinfo = &loopspec[n]->data.info;
3377 else
3378 specinfo = NULL;
3379 info = &ss->data.info;
3381 if (!specinfo)
3382 loopspec[n] = ss;
3383 /* Criteria for choosing a loop specifier (most important first):
3384 doesn't need realloc
3385 stride of one
3386 known stride
3387 known lower bound
3388 known upper bound
3390 else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
3391 loopspec[n] = ss;
3392 else if (integer_onep (info->stride[n])
3393 && !integer_onep (specinfo->stride[n]))
3394 loopspec[n] = ss;
3395 else if (INTEGER_CST_P (info->stride[n])
3396 && !INTEGER_CST_P (specinfo->stride[n]))
3397 loopspec[n] = ss;
3398 else if (INTEGER_CST_P (info->start[n])
3399 && !INTEGER_CST_P (specinfo->start[n]))
3400 loopspec[n] = ss;
3401 /* We don't work out the upper bound.
3402 else if (INTEGER_CST_P (info->finish[n])
3403 && ! INTEGER_CST_P (specinfo->finish[n]))
3404 loopspec[n] = ss; */
3407 /* We should have found the scalarization loop specifier. If not,
3408 that's bad news. */
3409 gcc_assert (loopspec[n]);
3411 info = &loopspec[n]->data.info;
3413 /* Set the extents of this range. */
3414 cshape = loopspec[n]->shape;
3415 if (cshape && INTEGER_CST_P (info->start[n])
3416 && INTEGER_CST_P (info->stride[n]))
3418 loop->from[n] = info->start[n];
3419 mpz_set (i, cshape[n]);
3420 mpz_sub_ui (i, i, 1);
3421 /* To = from + (size - 1) * stride. */
3422 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
3423 if (!integer_onep (info->stride[n]))
3424 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3425 tmp, info->stride[n]);
3426 loop->to[n] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3427 loop->from[n], tmp);
3429 else
3431 loop->from[n] = info->start[n];
3432 switch (loopspec[n]->type)
3434 case GFC_SS_CONSTRUCTOR:
3435 /* The upper bound is calculated when we expand the
3436 constructor. */
3437 gcc_assert (loop->to[n] == NULL_TREE);
3438 break;
3440 case GFC_SS_SECTION:
3441 loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
3442 &loop->pre);
3443 break;
3445 case GFC_SS_FUNCTION:
3446 /* The loop bound will be set when we generate the call. */
3447 gcc_assert (loop->to[n] == NULL_TREE);
3448 break;
3450 default:
3451 gcc_unreachable ();
3455 /* Transform everything so we have a simple incrementing variable. */
3456 if (integer_onep (info->stride[n]))
3457 info->delta[n] = gfc_index_zero_node;
3458 else
3460 /* Set the delta for this section. */
3461 info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
3462 /* Number of iterations is (end - start + step) / step.
3463 with start = 0, this simplifies to
3464 last = end / step;
3465 for (i = 0; i<=last; i++){...}; */
3466 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3467 loop->to[n], loop->from[n]);
3468 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type,
3469 tmp, info->stride[n]);
3470 tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
3471 build_int_cst (gfc_array_index_type, -1));
3472 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
3473 /* Make the loop variable start at 0. */
3474 loop->from[n] = gfc_index_zero_node;
3478 /* Add all the scalar code that can be taken out of the loops.
3479 This may include calculating the loop bounds, so do it before
3480 allocating the temporary. */
3481 gfc_add_loop_ss_code (loop, loop->ss, false);
3483 /* If we want a temporary then create it. */
3484 if (loop->temp_ss != NULL)
3486 gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
3488 /* Make absolutely sure that this is a complete type. */
3489 if (loop->temp_ss->string_length)
3490 loop->temp_ss->data.temp.type
3491 = gfc_get_character_type_len (gfc_default_character_kind,
3492 loop->temp_ss->string_length);
3494 tmp = loop->temp_ss->data.temp.type;
3495 len = loop->temp_ss->string_length;
3496 n = loop->temp_ss->data.temp.dimen;
3497 memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
3498 loop->temp_ss->type = GFC_SS_SECTION;
3499 loop->temp_ss->data.info.dimen = n;
3500 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
3501 &loop->temp_ss->data.info, tmp, false, true,
3502 false);
3505 for (n = 0; n < loop->temp_dim; n++)
3506 loopspec[loop->order[n]] = NULL;
3508 mpz_clear (i);
3510 /* For array parameters we don't have loop variables, so don't calculate the
3511 translations. */
3512 if (loop->array_parameter)
3513 return;
3515 /* Calculate the translation from loop variables to array indices. */
3516 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3518 if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT)
3519 continue;
3521 info = &ss->data.info;
3523 for (n = 0; n < info->dimen; n++)
3525 dim = info->dim[n];
3527 /* If we are specifying the range the delta is already set. */
3528 if (loopspec[n] != ss)
3530 /* Calculate the offset relative to the loop variable.
3531 First multiply by the stride. */
3532 tmp = loop->from[n];
3533 if (!integer_onep (info->stride[n]))
3534 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3535 tmp, info->stride[n]);
3537 /* Then subtract this from our starting value. */
3538 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3539 info->start[n], tmp);
3541 info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
3548 /* Fills in an array descriptor, and returns the size of the array. The size
3549 will be a simple_val, ie a variable or a constant. Also calculates the
3550 offset of the base. Returns the size of the array.
3552 stride = 1;
3553 offset = 0;
3554 for (n = 0; n < rank; n++)
3556 a.lbound[n] = specified_lower_bound;
3557 offset = offset + a.lbond[n] * stride;
3558 size = 1 - lbound;
3559 a.ubound[n] = specified_upper_bound;
3560 a.stride[n] = stride;
3561 size = siz >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
3562 stride = stride * size;
3564 return (stride);
3565 } */
3566 /*GCC ARRAYS*/
3568 static tree
3569 gfc_array_init_size (tree descriptor, int rank, tree * poffset,
3570 gfc_expr ** lower, gfc_expr ** upper,
3571 stmtblock_t * pblock)
3573 tree type;
3574 tree tmp;
3575 tree size;
3576 tree offset;
3577 tree stride;
3578 tree cond;
3579 tree or_expr;
3580 tree thencase;
3581 tree elsecase;
3582 tree var;
3583 stmtblock_t thenblock;
3584 stmtblock_t elseblock;
3585 gfc_expr *ubound;
3586 gfc_se se;
3587 int n;
3589 type = TREE_TYPE (descriptor);
3591 stride = gfc_index_one_node;
3592 offset = gfc_index_zero_node;
3594 /* Set the dtype. */
3595 tmp = gfc_conv_descriptor_dtype (descriptor);
3596 gfc_add_modify_expr (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
3598 or_expr = NULL_TREE;
3600 for (n = 0; n < rank; n++)
3602 /* We have 3 possibilities for determining the size of the array:
3603 lower == NULL => lbound = 1, ubound = upper[n]
3604 upper[n] = NULL => lbound = 1, ubound = lower[n]
3605 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
3606 ubound = upper[n];
3608 /* Set lower bound. */
3609 gfc_init_se (&se, NULL);
3610 if (lower == NULL)
3611 se.expr = gfc_index_one_node;
3612 else
3614 gcc_assert (lower[n]);
3615 if (ubound)
3617 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
3618 gfc_add_block_to_block (pblock, &se.pre);
3620 else
3622 se.expr = gfc_index_one_node;
3623 ubound = lower[n];
3626 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
3627 gfc_add_modify_expr (pblock, tmp, se.expr);
3629 /* Work out the offset for this component. */
3630 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
3631 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3633 /* Start the calculation for the size of this dimension. */
3634 size = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3635 gfc_index_one_node, se.expr);
3637 /* Set upper bound. */
3638 gfc_init_se (&se, NULL);
3639 gcc_assert (ubound);
3640 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
3641 gfc_add_block_to_block (pblock, &se.pre);
3643 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
3644 gfc_add_modify_expr (pblock, tmp, se.expr);
3646 /* Store the stride. */
3647 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
3648 gfc_add_modify_expr (pblock, tmp, stride);
3650 /* Calculate the size of this dimension. */
3651 size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
3653 /* Check whether the size for this dimension is negative. */
3654 cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3655 gfc_index_zero_node);
3656 if (n == 0)
3657 or_expr = cond;
3658 else
3659 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
3661 size = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
3662 gfc_index_zero_node, size);
3664 /* Multiply the stride by the number of elements in this dimension. */
3665 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, size);
3666 stride = gfc_evaluate_now (stride, pblock);
3669 /* The stride is the number of elements in the array, so multiply by the
3670 size of an element to get the total size. */
3671 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3672 size = fold_build2 (MULT_EXPR, gfc_array_index_type, stride,
3673 fold_convert (gfc_array_index_type, tmp));
3675 if (poffset != NULL)
3677 offset = gfc_evaluate_now (offset, pblock);
3678 *poffset = offset;
3681 if (integer_zerop (or_expr))
3682 return size;
3683 if (integer_onep (or_expr))
3684 return gfc_index_zero_node;
3686 var = gfc_create_var (TREE_TYPE (size), "size");
3687 gfc_start_block (&thenblock);
3688 gfc_add_modify_expr (&thenblock, var, gfc_index_zero_node);
3689 thencase = gfc_finish_block (&thenblock);
3691 gfc_start_block (&elseblock);
3692 gfc_add_modify_expr (&elseblock, var, size);
3693 elsecase = gfc_finish_block (&elseblock);
3695 tmp = gfc_evaluate_now (or_expr, pblock);
3696 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
3697 gfc_add_expr_to_block (pblock, tmp);
3699 return var;
3703 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
3704 the work for an ALLOCATE statement. */
3705 /*GCC ARRAYS*/
3707 bool
3708 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
3710 tree tmp;
3711 tree pointer;
3712 tree offset;
3713 tree size;
3714 gfc_expr **lower;
3715 gfc_expr **upper;
3716 gfc_ref *ref, *prev_ref = NULL;
3717 bool allocatable_array;
3719 ref = expr->ref;
3721 /* Find the last reference in the chain. */
3722 while (ref && ref->next != NULL)
3724 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
3725 prev_ref = ref;
3726 ref = ref->next;
3729 if (ref == NULL || ref->type != REF_ARRAY)
3730 return false;
3732 if (!prev_ref)
3733 allocatable_array = expr->symtree->n.sym->attr.allocatable;
3734 else
3735 allocatable_array = prev_ref->u.c.component->allocatable;
3737 /* Figure out the size of the array. */
3738 switch (ref->u.ar.type)
3740 case AR_ELEMENT:
3741 lower = NULL;
3742 upper = ref->u.ar.start;
3743 break;
3745 case AR_FULL:
3746 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
3748 lower = ref->u.ar.as->lower;
3749 upper = ref->u.ar.as->upper;
3750 break;
3752 case AR_SECTION:
3753 lower = ref->u.ar.start;
3754 upper = ref->u.ar.end;
3755 break;
3757 default:
3758 gcc_unreachable ();
3759 break;
3762 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
3763 lower, upper, &se->pre);
3765 /* Allocate memory to store the data. */
3766 pointer = gfc_conv_descriptor_data_get (se->expr);
3767 STRIP_NOPS (pointer);
3769 /* The allocate_array variants take the old pointer as first argument. */
3770 if (allocatable_array)
3771 tmp = gfc_allocate_array_with_status (&se->pre, pointer, size, pstat);
3772 else
3773 tmp = gfc_allocate_with_status (&se->pre, size, pstat);
3774 tmp = fold_build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
3775 gfc_add_expr_to_block (&se->pre, tmp);
3777 tmp = gfc_conv_descriptor_offset (se->expr);
3778 gfc_add_modify_expr (&se->pre, tmp, offset);
3780 if (expr->ts.type == BT_DERIVED
3781 && expr->ts.derived->attr.alloc_comp)
3783 tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
3784 ref->u.ar.as->rank);
3785 gfc_add_expr_to_block (&se->pre, tmp);
3788 return true;
3792 /* Deallocate an array variable. Also used when an allocated variable goes
3793 out of scope. */
3794 /*GCC ARRAYS*/
3796 tree
3797 gfc_array_deallocate (tree descriptor, tree pstat)
3799 tree var;
3800 tree tmp;
3801 stmtblock_t block;
3803 gfc_start_block (&block);
3804 /* Get a pointer to the data. */
3805 var = gfc_conv_descriptor_data_get (descriptor);
3806 STRIP_NOPS (var);
3808 /* Parameter is the address of the data component. */
3809 tmp = gfc_deallocate_with_status (var, pstat, false);
3810 gfc_add_expr_to_block (&block, tmp);
3812 /* Zero the data pointer. */
3813 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
3814 var, build_int_cst (TREE_TYPE (var), 0));
3815 gfc_add_expr_to_block (&block, tmp);
3817 return gfc_finish_block (&block);
3821 /* Create an array constructor from an initialization expression.
3822 We assume the frontend already did any expansions and conversions. */
3824 tree
3825 gfc_conv_array_initializer (tree type, gfc_expr * expr)
3827 gfc_constructor *c;
3828 tree tmp;
3829 mpz_t maxval;
3830 gfc_se se;
3831 HOST_WIDE_INT hi;
3832 unsigned HOST_WIDE_INT lo;
3833 tree index, range;
3834 VEC(constructor_elt,gc) *v = NULL;
3836 switch (expr->expr_type)
3838 case EXPR_CONSTANT:
3839 case EXPR_STRUCTURE:
3840 /* A single scalar or derived type value. Create an array with all
3841 elements equal to that value. */
3842 gfc_init_se (&se, NULL);
3844 if (expr->expr_type == EXPR_CONSTANT)
3845 gfc_conv_constant (&se, expr);
3846 else
3847 gfc_conv_structure (&se, expr, 1);
3849 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
3850 gcc_assert (tmp && INTEGER_CST_P (tmp));
3851 hi = TREE_INT_CST_HIGH (tmp);
3852 lo = TREE_INT_CST_LOW (tmp);
3853 lo++;
3854 if (lo == 0)
3855 hi++;
3856 /* This will probably eat buckets of memory for large arrays. */
3857 while (hi != 0 || lo != 0)
3859 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
3860 if (lo == 0)
3861 hi--;
3862 lo--;
3864 break;
3866 case EXPR_ARRAY:
3867 /* Create a vector of all the elements. */
3868 for (c = expr->value.constructor; c; c = c->next)
3870 if (c->iterator)
3872 /* Problems occur when we get something like
3873 integer :: a(lots) = (/(i, i=1,lots)/) */
3874 /* TODO: Unexpanded array initializers. */
3875 internal_error
3876 ("Possible frontend bug: array constructor not expanded");
3878 if (mpz_cmp_si (c->n.offset, 0) != 0)
3879 index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3880 else
3881 index = NULL_TREE;
3882 mpz_init (maxval);
3883 if (mpz_cmp_si (c->repeat, 0) != 0)
3885 tree tmp1, tmp2;
3887 mpz_set (maxval, c->repeat);
3888 mpz_add (maxval, c->n.offset, maxval);
3889 mpz_sub_ui (maxval, maxval, 1);
3890 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3891 if (mpz_cmp_si (c->n.offset, 0) != 0)
3893 mpz_add_ui (maxval, c->n.offset, 1);
3894 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
3896 else
3897 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
3899 range = fold_build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
3901 else
3902 range = NULL;
3903 mpz_clear (maxval);
3905 gfc_init_se (&se, NULL);
3906 switch (c->expr->expr_type)
3908 case EXPR_CONSTANT:
3909 gfc_conv_constant (&se, c->expr);
3910 if (range == NULL_TREE)
3911 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3912 else
3914 if (index != NULL_TREE)
3915 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3916 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
3918 break;
3920 case EXPR_STRUCTURE:
3921 gfc_conv_structure (&se, c->expr, 1);
3922 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
3923 break;
3925 default:
3926 gcc_unreachable ();
3929 break;
3931 case EXPR_NULL:
3932 return gfc_build_null_descriptor (type);
3934 default:
3935 gcc_unreachable ();
3938 /* Create a constructor from the list of elements. */
3939 tmp = build_constructor (type, v);
3940 TREE_CONSTANT (tmp) = 1;
3941 return tmp;
3945 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
3946 returns the size (in elements) of the array. */
3948 static tree
3949 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
3950 stmtblock_t * pblock)
3952 gfc_array_spec *as;
3953 tree size;
3954 tree stride;
3955 tree offset;
3956 tree ubound;
3957 tree lbound;
3958 tree tmp;
3959 gfc_se se;
3961 int dim;
3963 as = sym->as;
3965 size = gfc_index_one_node;
3966 offset = gfc_index_zero_node;
3967 for (dim = 0; dim < as->rank; dim++)
3969 /* Evaluate non-constant array bound expressions. */
3970 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
3971 if (as->lower[dim] && !INTEGER_CST_P (lbound))
3973 gfc_init_se (&se, NULL);
3974 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
3975 gfc_add_block_to_block (pblock, &se.pre);
3976 gfc_add_modify_expr (pblock, lbound, se.expr);
3978 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
3979 if (as->upper[dim] && !INTEGER_CST_P (ubound))
3981 gfc_init_se (&se, NULL);
3982 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
3983 gfc_add_block_to_block (pblock, &se.pre);
3984 gfc_add_modify_expr (pblock, ubound, se.expr);
3986 /* The offset of this dimension. offset = offset - lbound * stride. */
3987 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, size);
3988 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3990 /* The size of this dimension, and the stride of the next. */
3991 if (dim + 1 < as->rank)
3992 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
3993 else
3994 stride = GFC_TYPE_ARRAY_SIZE (type);
3996 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
3998 /* Calculate stride = size * (ubound + 1 - lbound). */
3999 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4000 gfc_index_one_node, lbound);
4001 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp);
4002 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
4003 if (stride)
4004 gfc_add_modify_expr (pblock, stride, tmp);
4005 else
4006 stride = gfc_evaluate_now (tmp, pblock);
4008 /* Make sure that negative size arrays are translated
4009 to being zero size. */
4010 tmp = fold_build2 (GE_EXPR, boolean_type_node,
4011 stride, gfc_index_zero_node);
4012 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, tmp,
4013 stride, gfc_index_zero_node);
4014 gfc_add_modify_expr (pblock, stride, tmp);
4017 size = stride;
4020 gfc_trans_vla_type_sizes (sym, pblock);
4022 *poffset = offset;
4023 return size;
4027 /* Generate code to initialize/allocate an array variable. */
4029 tree
4030 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
4032 stmtblock_t block;
4033 tree type;
4034 tree tmp;
4035 tree size;
4036 tree offset;
4037 bool onstack;
4039 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
4041 /* Do nothing for USEd variables. */
4042 if (sym->attr.use_assoc)
4043 return fnbody;
4045 type = TREE_TYPE (decl);
4046 gcc_assert (GFC_ARRAY_TYPE_P (type));
4047 onstack = TREE_CODE (type) != POINTER_TYPE;
4049 gfc_start_block (&block);
4051 /* Evaluate character string length. */
4052 if (sym->ts.type == BT_CHARACTER
4053 && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4055 gfc_conv_string_length (sym->ts.cl, &block);
4057 gfc_trans_vla_type_sizes (sym, &block);
4059 /* Emit a DECL_EXPR for this variable, which will cause the
4060 gimplifier to allocate storage, and all that good stuff. */
4061 tmp = fold_build1 (DECL_EXPR, TREE_TYPE (decl), decl);
4062 gfc_add_expr_to_block (&block, tmp);
4065 if (onstack)
4067 gfc_add_expr_to_block (&block, fnbody);
4068 return gfc_finish_block (&block);
4071 type = TREE_TYPE (type);
4073 gcc_assert (!sym->attr.use_assoc);
4074 gcc_assert (!TREE_STATIC (decl));
4075 gcc_assert (!sym->module);
4077 if (sym->ts.type == BT_CHARACTER
4078 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4079 gfc_conv_string_length (sym->ts.cl, &block);
4081 size = gfc_trans_array_bounds (type, sym, &offset, &block);
4083 /* Don't actually allocate space for Cray Pointees. */
4084 if (sym->attr.cray_pointee)
4086 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4087 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4088 gfc_add_expr_to_block (&block, fnbody);
4089 return gfc_finish_block (&block);
4092 /* The size is the number of elements in the array, so multiply by the
4093 size of an element to get the total size. */
4094 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4095 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
4096 fold_convert (gfc_array_index_type, tmp));
4098 /* Allocate memory to hold the data. */
4099 tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
4100 gfc_add_modify_expr (&block, decl, tmp);
4102 /* Set offset of the array. */
4103 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4104 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4107 /* Automatic arrays should not have initializers. */
4108 gcc_assert (!sym->value);
4110 gfc_add_expr_to_block (&block, fnbody);
4112 /* Free the temporary. */
4113 tmp = gfc_call_free (convert (pvoid_type_node, decl));
4114 gfc_add_expr_to_block (&block, tmp);
4116 return gfc_finish_block (&block);
4120 /* Generate entry and exit code for g77 calling convention arrays. */
4122 tree
4123 gfc_trans_g77_array (gfc_symbol * sym, tree body)
4125 tree parm;
4126 tree type;
4127 locus loc;
4128 tree offset;
4129 tree tmp;
4130 tree stmt;
4131 stmtblock_t block;
4133 gfc_get_backend_locus (&loc);
4134 gfc_set_backend_locus (&sym->declared_at);
4136 /* Descriptor type. */
4137 parm = sym->backend_decl;
4138 type = TREE_TYPE (parm);
4139 gcc_assert (GFC_ARRAY_TYPE_P (type));
4141 gfc_start_block (&block);
4143 if (sym->ts.type == BT_CHARACTER
4144 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4145 gfc_conv_string_length (sym->ts.cl, &block);
4147 /* Evaluate the bounds of the array. */
4148 gfc_trans_array_bounds (type, sym, &offset, &block);
4150 /* Set the offset. */
4151 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4152 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4154 /* Set the pointer itself if we aren't using the parameter directly. */
4155 if (TREE_CODE (parm) != PARM_DECL)
4157 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
4158 gfc_add_modify_expr (&block, parm, tmp);
4160 stmt = gfc_finish_block (&block);
4162 gfc_set_backend_locus (&loc);
4164 gfc_start_block (&block);
4166 /* Add the initialization code to the start of the function. */
4168 if (sym->attr.optional || sym->attr.not_always_present)
4170 tmp = gfc_conv_expr_present (sym);
4171 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4174 gfc_add_expr_to_block (&block, stmt);
4175 gfc_add_expr_to_block (&block, body);
4177 return gfc_finish_block (&block);
4181 /* Modify the descriptor of an array parameter so that it has the
4182 correct lower bound. Also move the upper bound accordingly.
4183 If the array is not packed, it will be copied into a temporary.
4184 For each dimension we set the new lower and upper bounds. Then we copy the
4185 stride and calculate the offset for this dimension. We also work out
4186 what the stride of a packed array would be, and see it the two match.
4187 If the array need repacking, we set the stride to the values we just
4188 calculated, recalculate the offset and copy the array data.
4189 Code is also added to copy the data back at the end of the function.
4192 tree
4193 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
4195 tree size;
4196 tree type;
4197 tree offset;
4198 locus loc;
4199 stmtblock_t block;
4200 stmtblock_t cleanup;
4201 tree lbound;
4202 tree ubound;
4203 tree dubound;
4204 tree dlbound;
4205 tree dumdesc;
4206 tree tmp;
4207 tree stmt;
4208 tree stride, stride2;
4209 tree stmt_packed;
4210 tree stmt_unpacked;
4211 tree partial;
4212 gfc_se se;
4213 int n;
4214 int checkparm;
4215 int no_repack;
4216 bool optional_arg;
4218 /* Do nothing for pointer and allocatable arrays. */
4219 if (sym->attr.pointer || sym->attr.allocatable)
4220 return body;
4222 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
4223 return gfc_trans_g77_array (sym, body);
4225 gfc_get_backend_locus (&loc);
4226 gfc_set_backend_locus (&sym->declared_at);
4228 /* Descriptor type. */
4229 type = TREE_TYPE (tmpdesc);
4230 gcc_assert (GFC_ARRAY_TYPE_P (type));
4231 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4232 dumdesc = build_fold_indirect_ref (dumdesc);
4233 gfc_start_block (&block);
4235 if (sym->ts.type == BT_CHARACTER
4236 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4237 gfc_conv_string_length (sym->ts.cl, &block);
4239 checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);
4241 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
4242 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
4244 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
4246 /* For non-constant shape arrays we only check if the first dimension
4247 is contiguous. Repacking higher dimensions wouldn't gain us
4248 anything as we still don't know the array stride. */
4249 partial = gfc_create_var (boolean_type_node, "partial");
4250 TREE_USED (partial) = 1;
4251 tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4252 tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
4253 gfc_add_modify_expr (&block, partial, tmp);
4255 else
4257 partial = NULL_TREE;
4260 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
4261 here, however I think it does the right thing. */
4262 if (no_repack)
4264 /* Set the first stride. */
4265 stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4266 stride = gfc_evaluate_now (stride, &block);
4268 tmp = fold_build2 (EQ_EXPR, boolean_type_node,
4269 stride, gfc_index_zero_node);
4270 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, tmp,
4271 gfc_index_one_node, stride);
4272 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
4273 gfc_add_modify_expr (&block, stride, tmp);
4275 /* Allow the user to disable array repacking. */
4276 stmt_unpacked = NULL_TREE;
4278 else
4280 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
4281 /* A library call to repack the array if necessary. */
4282 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4283 stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
4285 stride = gfc_index_one_node;
4288 /* This is for the case where the array data is used directly without
4289 calling the repack function. */
4290 if (no_repack || partial != NULL_TREE)
4291 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
4292 else
4293 stmt_packed = NULL_TREE;
4295 /* Assign the data pointer. */
4296 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4298 /* Don't repack unknown shape arrays when the first stride is 1. */
4299 tmp = fold_build3 (COND_EXPR, TREE_TYPE (stmt_packed),
4300 partial, stmt_packed, stmt_unpacked);
4302 else
4303 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
4304 gfc_add_modify_expr (&block, tmpdesc, fold_convert (type, tmp));
4306 offset = gfc_index_zero_node;
4307 size = gfc_index_one_node;
4309 /* Evaluate the bounds of the array. */
4310 for (n = 0; n < sym->as->rank; n++)
4312 if (checkparm || !sym->as->upper[n])
4314 /* Get the bounds of the actual parameter. */
4315 dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
4316 dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
4318 else
4320 dubound = NULL_TREE;
4321 dlbound = NULL_TREE;
4324 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
4325 if (!INTEGER_CST_P (lbound))
4327 gfc_init_se (&se, NULL);
4328 gfc_conv_expr_type (&se, sym->as->lower[n],
4329 gfc_array_index_type);
4330 gfc_add_block_to_block (&block, &se.pre);
4331 gfc_add_modify_expr (&block, lbound, se.expr);
4334 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
4335 /* Set the desired upper bound. */
4336 if (sym->as->upper[n])
4338 /* We know what we want the upper bound to be. */
4339 if (!INTEGER_CST_P (ubound))
4341 gfc_init_se (&se, NULL);
4342 gfc_conv_expr_type (&se, sym->as->upper[n],
4343 gfc_array_index_type);
4344 gfc_add_block_to_block (&block, &se.pre);
4345 gfc_add_modify_expr (&block, ubound, se.expr);
4348 /* Check the sizes match. */
4349 if (checkparm)
4351 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
4352 char * msg;
4354 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4355 ubound, lbound);
4356 stride2 = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4357 dubound, dlbound);
4358 tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
4359 asprintf (&msg, "%s for dimension %d of array '%s'",
4360 gfc_msg_bounds, n+1, sym->name);
4361 gfc_trans_runtime_check (tmp, &block, &loc, msg);
4362 gfc_free (msg);
4365 else
4367 /* For assumed shape arrays move the upper bound by the same amount
4368 as the lower bound. */
4369 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4370 dubound, dlbound);
4371 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound);
4372 gfc_add_modify_expr (&block, ubound, tmp);
4374 /* The offset of this dimension. offset = offset - lbound * stride. */
4375 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, stride);
4376 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
4378 /* The size of this dimension, and the stride of the next. */
4379 if (n + 1 < sym->as->rank)
4381 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
4383 if (no_repack || partial != NULL_TREE)
4385 stmt_unpacked =
4386 gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
4389 /* Figure out the stride if not a known constant. */
4390 if (!INTEGER_CST_P (stride))
4392 if (no_repack)
4393 stmt_packed = NULL_TREE;
4394 else
4396 /* Calculate stride = size * (ubound + 1 - lbound). */
4397 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4398 gfc_index_one_node, lbound);
4399 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4400 ubound, tmp);
4401 size = fold_build2 (MULT_EXPR, gfc_array_index_type,
4402 size, tmp);
4403 stmt_packed = size;
4406 /* Assign the stride. */
4407 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4408 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, partial,
4409 stmt_unpacked, stmt_packed);
4410 else
4411 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
4412 gfc_add_modify_expr (&block, stride, tmp);
4415 else
4417 stride = GFC_TYPE_ARRAY_SIZE (type);
4419 if (stride && !INTEGER_CST_P (stride))
4421 /* Calculate size = stride * (ubound + 1 - lbound). */
4422 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4423 gfc_index_one_node, lbound);
4424 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4425 ubound, tmp);
4426 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4427 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
4428 gfc_add_modify_expr (&block, stride, tmp);
4433 /* Set the offset. */
4434 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4435 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4437 gfc_trans_vla_type_sizes (sym, &block);
4439 stmt = gfc_finish_block (&block);
4441 gfc_start_block (&block);
4443 /* Only do the entry/initialization code if the arg is present. */
4444 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4445 optional_arg = (sym->attr.optional
4446 || (sym->ns->proc_name->attr.entry_master
4447 && sym->attr.dummy));
4448 if (optional_arg)
4450 tmp = gfc_conv_expr_present (sym);
4451 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4453 gfc_add_expr_to_block (&block, stmt);
4455 /* Add the main function body. */
4456 gfc_add_expr_to_block (&block, body);
4458 /* Cleanup code. */
4459 if (!no_repack)
4461 gfc_start_block (&cleanup);
4463 if (sym->attr.intent != INTENT_IN)
4465 /* Copy the data back. */
4466 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
4467 gfc_add_expr_to_block (&cleanup, tmp);
4470 /* Free the temporary. */
4471 tmp = gfc_call_free (tmpdesc);
4472 gfc_add_expr_to_block (&cleanup, tmp);
4474 stmt = gfc_finish_block (&cleanup);
4476 /* Only do the cleanup if the array was repacked. */
4477 tmp = build_fold_indirect_ref (dumdesc);
4478 tmp = gfc_conv_descriptor_data_get (tmp);
4479 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
4480 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4482 if (optional_arg)
4484 tmp = gfc_conv_expr_present (sym);
4485 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4487 gfc_add_expr_to_block (&block, stmt);
4489 /* We don't need to free any memory allocated by internal_pack as it will
4490 be freed at the end of the function by pop_context. */
4491 return gfc_finish_block (&block);
4495 /* Calculate the overall offset, including subreferences. */
4496 static void
4497 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
4498 bool subref, gfc_expr *expr)
4500 tree tmp;
4501 tree field;
4502 tree stride;
4503 tree index;
4504 gfc_ref *ref;
4505 gfc_se start;
4506 int n;
4508 /* If offset is NULL and this is not a subreferenced array, there is
4509 nothing to do. */
4510 if (offset == NULL_TREE)
4512 if (subref)
4513 offset = gfc_index_zero_node;
4514 else
4515 return;
4518 tmp = gfc_conv_array_data (desc);
4519 tmp = build_fold_indirect_ref (tmp);
4520 tmp = gfc_build_array_ref (tmp, offset, NULL);
4522 /* Offset the data pointer for pointer assignments from arrays with
4523 subreferences; eg. my_integer => my_type(:)%integer_component. */
4524 if (subref)
4526 /* Go past the array reference. */
4527 for (ref = expr->ref; ref; ref = ref->next)
4528 if (ref->type == REF_ARRAY &&
4529 ref->u.ar.type != AR_ELEMENT)
4531 ref = ref->next;
4532 break;
4535 /* Calculate the offset for each subsequent subreference. */
4536 for (; ref; ref = ref->next)
4538 switch (ref->type)
4540 case REF_COMPONENT:
4541 field = ref->u.c.component->backend_decl;
4542 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
4543 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
4544 tmp, field, NULL_TREE);
4545 break;
4547 case REF_SUBSTRING:
4548 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
4549 gfc_init_se (&start, NULL);
4550 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
4551 gfc_add_block_to_block (block, &start.pre);
4552 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
4553 break;
4555 case REF_ARRAY:
4556 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
4557 && ref->u.ar.type == AR_ELEMENT);
4559 /* TODO - Add bounds checking. */
4560 stride = gfc_index_one_node;
4561 index = gfc_index_zero_node;
4562 for (n = 0; n < ref->u.ar.dimen; n++)
4564 tree itmp;
4565 tree jtmp;
4567 /* Update the index. */
4568 gfc_init_se (&start, NULL);
4569 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
4570 itmp = gfc_evaluate_now (start.expr, block);
4571 gfc_init_se (&start, NULL);
4572 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
4573 jtmp = gfc_evaluate_now (start.expr, block);
4574 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, itmp, jtmp);
4575 itmp = fold_build2 (MULT_EXPR, gfc_array_index_type, itmp, stride);
4576 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, itmp, index);
4577 index = gfc_evaluate_now (index, block);
4579 /* Update the stride. */
4580 gfc_init_se (&start, NULL);
4581 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
4582 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, start.expr, jtmp);
4583 itmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4584 gfc_index_one_node, itmp);
4585 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, itmp);
4586 stride = gfc_evaluate_now (stride, block);
4589 /* Apply the index to obtain the array element. */
4590 tmp = gfc_build_array_ref (tmp, index, NULL);
4591 break;
4593 default:
4594 gcc_unreachable ();
4595 break;
4600 /* Set the target data pointer. */
4601 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
4602 gfc_conv_descriptor_data_set (block, parm, offset);
4606 /* gfc_conv_expr_descriptor needs the character length of elemental
4607 functions before the function is called so that the size of the
4608 temporary can be obtained. The only way to do this is to convert
4609 the expression, mapping onto the actual arguments. */
4610 static void
4611 get_elemental_fcn_charlen (gfc_expr *expr, gfc_se *se)
4613 gfc_interface_mapping mapping;
4614 gfc_formal_arglist *formal;
4615 gfc_actual_arglist *arg;
4616 gfc_se tse;
4618 formal = expr->symtree->n.sym->formal;
4619 arg = expr->value.function.actual;
4620 gfc_init_interface_mapping (&mapping);
4622 /* Set se = NULL in the calls to the interface mapping, to supress any
4623 backend stuff. */
4624 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
4626 if (!arg->expr)
4627 continue;
4628 if (formal->sym)
4629 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
4632 gfc_init_se (&tse, NULL);
4634 /* Build the expression for the character length and convert it. */
4635 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.cl->length);
4637 gfc_add_block_to_block (&se->pre, &tse.pre);
4638 gfc_add_block_to_block (&se->post, &tse.post);
4639 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
4640 tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
4641 build_int_cst (gfc_charlen_type_node, 0));
4642 expr->ts.cl->backend_decl = tse.expr;
4643 gfc_free_interface_mapping (&mapping);
4647 /* Convert an array for passing as an actual argument. Expressions and
4648 vector subscripts are evaluated and stored in a temporary, which is then
4649 passed. For whole arrays the descriptor is passed. For array sections
4650 a modified copy of the descriptor is passed, but using the original data.
4652 This function is also used for array pointer assignments, and there
4653 are three cases:
4655 - se->want_pointer && !se->direct_byref
4656 EXPR is an actual argument. On exit, se->expr contains a
4657 pointer to the array descriptor.
4659 - !se->want_pointer && !se->direct_byref
4660 EXPR is an actual argument to an intrinsic function or the
4661 left-hand side of a pointer assignment. On exit, se->expr
4662 contains the descriptor for EXPR.
4664 - !se->want_pointer && se->direct_byref
4665 EXPR is the right-hand side of a pointer assignment and
4666 se->expr is the descriptor for the previously-evaluated
4667 left-hand side. The function creates an assignment from
4668 EXPR to se->expr. */
4670 void
4671 gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
4673 gfc_loopinfo loop;
4674 gfc_ss *secss;
4675 gfc_ss_info *info;
4676 int need_tmp;
4677 int n;
4678 tree tmp;
4679 tree desc;
4680 stmtblock_t block;
4681 tree start;
4682 tree offset;
4683 int full;
4684 bool subref_array_target = false;
4686 gcc_assert (ss != gfc_ss_terminator);
4688 /* Special case things we know we can pass easily. */
4689 switch (expr->expr_type)
4691 case EXPR_VARIABLE:
4692 /* If we have a linear array section, we can pass it directly.
4693 Otherwise we need to copy it into a temporary. */
4695 /* Find the SS for the array section. */
4696 secss = ss;
4697 while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
4698 secss = secss->next;
4700 gcc_assert (secss != gfc_ss_terminator);
4701 info = &secss->data.info;
4703 /* Get the descriptor for the array. */
4704 gfc_conv_ss_descriptor (&se->pre, secss, 0);
4705 desc = info->descriptor;
4707 subref_array_target = se->direct_byref && is_subref_array (expr);
4708 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
4709 && !subref_array_target;
4711 if (need_tmp)
4712 full = 0;
4713 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4715 /* Create a new descriptor if the array doesn't have one. */
4716 full = 0;
4718 else if (info->ref->u.ar.type == AR_FULL)
4719 full = 1;
4720 else if (se->direct_byref)
4721 full = 0;
4722 else
4723 full = gfc_full_array_ref_p (info->ref);
4725 if (full)
4727 if (se->direct_byref)
4729 /* Copy the descriptor for pointer assignments. */
4730 gfc_add_modify_expr (&se->pre, se->expr, desc);
4732 /* Add any offsets from subreferences. */
4733 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
4734 subref_array_target, expr);
4736 else if (se->want_pointer)
4738 /* We pass full arrays directly. This means that pointers and
4739 allocatable arrays should also work. */
4740 se->expr = build_fold_addr_expr (desc);
4742 else
4744 se->expr = desc;
4747 if (expr->ts.type == BT_CHARACTER)
4748 se->string_length = gfc_get_expr_charlen (expr);
4750 return;
4752 break;
4754 case EXPR_FUNCTION:
4755 /* A transformational function return value will be a temporary
4756 array descriptor. We still need to go through the scalarizer
4757 to create the descriptor. Elemental functions ar handled as
4758 arbitrary expressions, i.e. copy to a temporary. */
4759 secss = ss;
4760 /* Look for the SS for this function. */
4761 while (secss != gfc_ss_terminator
4762 && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
4763 secss = secss->next;
4765 if (se->direct_byref)
4767 gcc_assert (secss != gfc_ss_terminator);
4769 /* For pointer assignments pass the descriptor directly. */
4770 se->ss = secss;
4771 se->expr = build_fold_addr_expr (se->expr);
4772 gfc_conv_expr (se, expr);
4773 return;
4776 if (secss == gfc_ss_terminator)
4778 /* Elemental function. */
4779 need_tmp = 1;
4780 if (expr->ts.type == BT_CHARACTER
4781 && expr->ts.cl->length->expr_type != EXPR_CONSTANT)
4782 get_elemental_fcn_charlen (expr, se);
4784 info = NULL;
4786 else
4788 /* Transformational function. */
4789 info = &secss->data.info;
4790 need_tmp = 0;
4792 break;
4794 case EXPR_ARRAY:
4795 /* Constant array constructors don't need a temporary. */
4796 if (ss->type == GFC_SS_CONSTRUCTOR
4797 && expr->ts.type != BT_CHARACTER
4798 && gfc_constant_array_constructor_p (expr->value.constructor))
4800 need_tmp = 0;
4801 info = &ss->data.info;
4802 secss = ss;
4804 else
4806 need_tmp = 1;
4807 secss = NULL;
4808 info = NULL;
4810 break;
4812 default:
4813 /* Something complicated. Copy it into a temporary. */
4814 need_tmp = 1;
4815 secss = NULL;
4816 info = NULL;
4817 break;
4821 gfc_init_loopinfo (&loop);
4823 /* Associate the SS with the loop. */
4824 gfc_add_ss_to_loop (&loop, ss);
4826 /* Tell the scalarizer not to bother creating loop variables, etc. */
4827 if (!need_tmp)
4828 loop.array_parameter = 1;
4829 else
4830 /* The right-hand side of a pointer assignment mustn't use a temporary. */
4831 gcc_assert (!se->direct_byref);
4833 /* Setup the scalarizing loops and bounds. */
4834 gfc_conv_ss_startstride (&loop);
4836 if (need_tmp)
4838 /* Tell the scalarizer to make a temporary. */
4839 loop.temp_ss = gfc_get_ss ();
4840 loop.temp_ss->type = GFC_SS_TEMP;
4841 loop.temp_ss->next = gfc_ss_terminator;
4843 if (expr->ts.type == BT_CHARACTER && !expr->ts.cl->backend_decl)
4844 gfc_conv_string_length (expr->ts.cl, &se->pre);
4846 loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
4848 if (expr->ts.type == BT_CHARACTER)
4849 loop.temp_ss->string_length = expr->ts.cl->backend_decl;
4850 else
4851 loop.temp_ss->string_length = NULL;
4853 se->string_length = loop.temp_ss->string_length;
4854 loop.temp_ss->data.temp.dimen = loop.dimen;
4855 gfc_add_ss_to_loop (&loop, loop.temp_ss);
4858 gfc_conv_loop_setup (&loop);
4860 if (need_tmp)
4862 /* Copy into a temporary and pass that. We don't need to copy the data
4863 back because expressions and vector subscripts must be INTENT_IN. */
4864 /* TODO: Optimize passing function return values. */
4865 gfc_se lse;
4866 gfc_se rse;
4868 /* Start the copying loops. */
4869 gfc_mark_ss_chain_used (loop.temp_ss, 1);
4870 gfc_mark_ss_chain_used (ss, 1);
4871 gfc_start_scalarized_body (&loop, &block);
4873 /* Copy each data element. */
4874 gfc_init_se (&lse, NULL);
4875 gfc_copy_loopinfo_to_se (&lse, &loop);
4876 gfc_init_se (&rse, NULL);
4877 gfc_copy_loopinfo_to_se (&rse, &loop);
4879 lse.ss = loop.temp_ss;
4880 rse.ss = ss;
4882 gfc_conv_scalarized_array_ref (&lse, NULL);
4883 if (expr->ts.type == BT_CHARACTER)
4885 gfc_conv_expr (&rse, expr);
4886 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
4887 rse.expr = build_fold_indirect_ref (rse.expr);
4889 else
4890 gfc_conv_expr_val (&rse, expr);
4892 gfc_add_block_to_block (&block, &rse.pre);
4893 gfc_add_block_to_block (&block, &lse.pre);
4895 lse.string_length = rse.string_length;
4896 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
4897 expr->expr_type == EXPR_VARIABLE);
4898 gfc_add_expr_to_block (&block, tmp);
4900 /* Finish the copying loops. */
4901 gfc_trans_scalarizing_loops (&loop, &block);
4903 desc = loop.temp_ss->data.info.descriptor;
4905 gcc_assert (is_gimple_lvalue (desc));
4907 else if (expr->expr_type == EXPR_FUNCTION)
4909 desc = info->descriptor;
4910 se->string_length = ss->string_length;
4912 else
4914 /* We pass sections without copying to a temporary. Make a new
4915 descriptor and point it at the section we want. The loop variable
4916 limits will be the limits of the section.
4917 A function may decide to repack the array to speed up access, but
4918 we're not bothered about that here. */
4919 int dim, ndim;
4920 tree parm;
4921 tree parmtype;
4922 tree stride;
4923 tree from;
4924 tree to;
4925 tree base;
4927 /* Set the string_length for a character array. */
4928 if (expr->ts.type == BT_CHARACTER)
4929 se->string_length = gfc_get_expr_charlen (expr);
4931 desc = info->descriptor;
4932 gcc_assert (secss && secss != gfc_ss_terminator);
4933 if (se->direct_byref)
4935 /* For pointer assignments we fill in the destination. */
4936 parm = se->expr;
4937 parmtype = TREE_TYPE (parm);
4939 else
4941 /* Otherwise make a new one. */
4942 parmtype = gfc_get_element_type (TREE_TYPE (desc));
4943 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
4944 loop.from, loop.to, 0,
4945 GFC_ARRAY_UNKNOWN);
4946 parm = gfc_create_var (parmtype, "parm");
4949 offset = gfc_index_zero_node;
4950 dim = 0;
4952 /* The following can be somewhat confusing. We have two
4953 descriptors, a new one and the original array.
4954 {parm, parmtype, dim} refer to the new one.
4955 {desc, type, n, secss, loop} refer to the original, which maybe
4956 a descriptorless array.
4957 The bounds of the scalarization are the bounds of the section.
4958 We don't have to worry about numeric overflows when calculating
4959 the offsets because all elements are within the array data. */
4961 /* Set the dtype. */
4962 tmp = gfc_conv_descriptor_dtype (parm);
4963 gfc_add_modify_expr (&loop.pre, tmp, gfc_get_dtype (parmtype));
4965 /* Set offset for assignments to pointer only to zero if it is not
4966 the full array. */
4967 if (se->direct_byref
4968 && info->ref && info->ref->u.ar.type != AR_FULL)
4969 base = gfc_index_zero_node;
4970 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
4971 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
4972 else
4973 base = NULL_TREE;
4975 ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
4976 for (n = 0; n < ndim; n++)
4978 stride = gfc_conv_array_stride (desc, n);
4980 /* Work out the offset. */
4981 if (info->ref
4982 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
4984 gcc_assert (info->subscript[n]
4985 && info->subscript[n]->type == GFC_SS_SCALAR);
4986 start = info->subscript[n]->data.scalar.expr;
4988 else
4990 /* Check we haven't somehow got out of sync. */
4991 gcc_assert (info->dim[dim] == n);
4993 /* Evaluate and remember the start of the section. */
4994 start = info->start[dim];
4995 stride = gfc_evaluate_now (stride, &loop.pre);
4998 tmp = gfc_conv_array_lbound (desc, n);
4999 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp);
5001 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
5002 offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
5004 if (info->ref
5005 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
5007 /* For elemental dimensions, we only need the offset. */
5008 continue;
5011 /* Vector subscripts need copying and are handled elsewhere. */
5012 if (info->ref)
5013 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
5015 /* Set the new lower bound. */
5016 from = loop.from[dim];
5017 to = loop.to[dim];
5019 /* If we have an array section or are assigning make sure that
5020 the lower bound is 1. References to the full
5021 array should otherwise keep the original bounds. */
5022 if ((!info->ref
5023 || info->ref->u.ar.type != AR_FULL)
5024 && !integer_onep (from))
5026 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
5027 gfc_index_one_node, from);
5028 to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
5029 from = gfc_index_one_node;
5031 tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
5032 gfc_add_modify_expr (&loop.pre, tmp, from);
5034 /* Set the new upper bound. */
5035 tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
5036 gfc_add_modify_expr (&loop.pre, tmp, to);
5038 /* Multiply the stride by the section stride to get the
5039 total stride. */
5040 stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
5041 stride, info->stride[dim]);
5043 if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
5045 base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
5046 base, stride);
5048 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5050 tmp = gfc_conv_array_lbound (desc, n);
5051 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
5052 tmp, loop.from[dim]);
5053 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base),
5054 tmp, gfc_conv_array_stride (desc, n));
5055 base = fold_build2 (PLUS_EXPR, TREE_TYPE (base),
5056 tmp, base);
5059 /* Store the new stride. */
5060 tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
5061 gfc_add_modify_expr (&loop.pre, tmp, stride);
5063 dim++;
5066 if (se->data_not_needed)
5067 gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
5068 else
5069 /* Point the data pointer at the first element in the section. */
5070 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
5071 subref_array_target, expr);
5073 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5074 && !se->data_not_needed)
5076 /* Set the offset. */
5077 tmp = gfc_conv_descriptor_offset (parm);
5078 gfc_add_modify_expr (&loop.pre, tmp, base);
5080 else
5082 /* Only the callee knows what the correct offset it, so just set
5083 it to zero here. */
5084 tmp = gfc_conv_descriptor_offset (parm);
5085 gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
5087 desc = parm;
5090 if (!se->direct_byref)
5092 /* Get a pointer to the new descriptor. */
5093 if (se->want_pointer)
5094 se->expr = build_fold_addr_expr (desc);
5095 else
5096 se->expr = desc;
5099 gfc_add_block_to_block (&se->pre, &loop.pre);
5100 gfc_add_block_to_block (&se->post, &loop.post);
5102 /* Cleanup the scalarizer. */
5103 gfc_cleanup_loop (&loop);
5107 /* Convert an array for passing as an actual parameter. */
5108 /* TODO: Optimize passing g77 arrays. */
5110 void
5111 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
5113 tree ptr;
5114 tree desc;
5115 tree tmp = NULL_TREE;
5116 tree stmt;
5117 tree parent = DECL_CONTEXT (current_function_decl);
5118 bool full_array_var, this_array_result;
5119 gfc_symbol *sym;
5120 stmtblock_t block;
5122 full_array_var = (expr->expr_type == EXPR_VARIABLE
5123 && expr->ref->u.ar.type == AR_FULL);
5124 sym = full_array_var ? expr->symtree->n.sym : NULL;
5126 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
5128 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
5129 expr->ts.cl->backend_decl = tmp;
5130 se->string_length = tmp;
5133 /* Is this the result of the enclosing procedure? */
5134 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
5135 if (this_array_result
5136 && (sym->backend_decl != current_function_decl)
5137 && (sym->backend_decl != parent))
5138 this_array_result = false;
5140 /* Passing address of the array if it is not pointer or assumed-shape. */
5141 if (full_array_var && g77 && !this_array_result)
5143 tmp = gfc_get_symbol_decl (sym);
5145 if (sym->ts.type == BT_CHARACTER)
5146 se->string_length = sym->ts.cl->backend_decl;
5147 if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE
5148 && !sym->attr.allocatable)
5150 /* Some variables are declared directly, others are declared as
5151 pointers and allocated on the heap. */
5152 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
5153 se->expr = tmp;
5154 else
5155 se->expr = build_fold_addr_expr (tmp);
5156 return;
5158 if (sym->attr.allocatable)
5160 if (sym->attr.dummy || sym->attr.result)
5162 gfc_conv_expr_descriptor (se, expr, ss);
5163 se->expr = gfc_conv_array_data (se->expr);
5165 else
5166 se->expr = gfc_conv_array_data (tmp);
5167 return;
5171 if (this_array_result)
5173 /* Result of the enclosing function. */
5174 gfc_conv_expr_descriptor (se, expr, ss);
5175 se->expr = build_fold_addr_expr (se->expr);
5177 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
5178 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
5179 se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
5181 return;
5183 else
5185 /* Every other type of array. */
5186 se->want_pointer = 1;
5187 gfc_conv_expr_descriptor (se, expr, ss);
5191 /* Deallocate the allocatable components of structures that are
5192 not variable. */
5193 if (expr->ts.type == BT_DERIVED
5194 && expr->ts.derived->attr.alloc_comp
5195 && expr->expr_type != EXPR_VARIABLE)
5197 tmp = build_fold_indirect_ref (se->expr);
5198 tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
5199 gfc_add_expr_to_block (&se->post, tmp);
5202 if (g77)
5204 desc = se->expr;
5205 /* Repack the array. */
5206 ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
5207 ptr = gfc_evaluate_now (ptr, &se->pre);
5208 se->expr = ptr;
5210 gfc_start_block (&block);
5212 /* Copy the data back. */
5213 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
5214 gfc_add_expr_to_block (&block, tmp);
5216 /* Free the temporary. */
5217 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
5218 gfc_add_expr_to_block (&block, tmp);
5220 stmt = gfc_finish_block (&block);
5222 gfc_init_block (&block);
5223 /* Only if it was repacked. This code needs to be executed before the
5224 loop cleanup code. */
5225 tmp = build_fold_indirect_ref (desc);
5226 tmp = gfc_conv_array_data (tmp);
5227 tmp = fold_build2 (NE_EXPR, boolean_type_node,
5228 fold_convert (TREE_TYPE (tmp), ptr), tmp);
5229 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
5231 gfc_add_expr_to_block (&block, tmp);
5232 gfc_add_block_to_block (&block, &se->post);
5234 gfc_init_block (&se->post);
5235 gfc_add_block_to_block (&se->post, &block);
5240 /* Generate code to deallocate an array, if it is allocated. */
5242 tree
5243 gfc_trans_dealloc_allocated (tree descriptor)
5245 tree tmp;
5246 tree var;
5247 stmtblock_t block;
5249 gfc_start_block (&block);
5251 var = gfc_conv_descriptor_data_get (descriptor);
5252 STRIP_NOPS (var);
5254 /* Call array_deallocate with an int * present in the second argument.
5255 Although it is ignored here, it's presence ensures that arrays that
5256 are already deallocated are ignored. */
5257 tmp = gfc_deallocate_with_status (var, NULL_TREE, true);
5258 gfc_add_expr_to_block (&block, tmp);
5260 /* Zero the data pointer. */
5261 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
5262 var, build_int_cst (TREE_TYPE (var), 0));
5263 gfc_add_expr_to_block (&block, tmp);
5265 return gfc_finish_block (&block);
5269 /* This helper function calculates the size in words of a full array. */
5271 static tree
5272 get_full_array_size (stmtblock_t *block, tree decl, int rank)
5274 tree idx;
5275 tree nelems;
5276 tree tmp;
5277 idx = gfc_rank_cst[rank - 1];
5278 nelems = gfc_conv_descriptor_ubound (decl, idx);
5279 tmp = gfc_conv_descriptor_lbound (decl, idx);
5280 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
5281 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
5282 tmp, gfc_index_one_node);
5283 tmp = gfc_evaluate_now (tmp, block);
5285 nelems = gfc_conv_descriptor_stride (decl, idx);
5286 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
5287 return gfc_evaluate_now (tmp, block);
5291 /* Allocate dest to the same size as src, and copy src -> dest. */
5293 tree
5294 gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
5296 tree tmp;
5297 tree size;
5298 tree nelems;
5299 tree null_cond;
5300 tree null_data;
5301 stmtblock_t block;
5303 /* If the source is null, set the destination to null. */
5304 gfc_init_block (&block);
5305 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
5306 null_data = gfc_finish_block (&block);
5308 gfc_init_block (&block);
5310 nelems = get_full_array_size (&block, src, rank);
5311 size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
5312 fold_convert (gfc_array_index_type,
5313 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
5315 /* Allocate memory to the destination. */
5316 tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
5317 size);
5318 gfc_conv_descriptor_data_set (&block, dest, tmp);
5320 /* We know the temporary and the value will be the same length,
5321 so can use memcpy. */
5322 tmp = built_in_decls[BUILT_IN_MEMCPY];
5323 tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
5324 gfc_conv_descriptor_data_get (src), size);
5325 gfc_add_expr_to_block (&block, tmp);
5326 tmp = gfc_finish_block (&block);
5328 /* Null the destination if the source is null; otherwise do
5329 the allocate and copy. */
5330 null_cond = gfc_conv_descriptor_data_get (src);
5331 null_cond = convert (pvoid_type_node, null_cond);
5332 null_cond = fold_build2 (NE_EXPR, boolean_type_node,
5333 null_cond, null_pointer_node);
5334 return build3_v (COND_EXPR, null_cond, tmp, null_data);
5338 /* Recursively traverse an object of derived type, generating code to
5339 deallocate, nullify or copy allocatable components. This is the work horse
5340 function for the functions named in this enum. */
5342 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
5344 static tree
5345 structure_alloc_comps (gfc_symbol * der_type, tree decl,
5346 tree dest, int rank, int purpose)
5348 gfc_component *c;
5349 gfc_loopinfo loop;
5350 stmtblock_t fnblock;
5351 stmtblock_t loopbody;
5352 tree tmp;
5353 tree comp;
5354 tree dcmp;
5355 tree nelems;
5356 tree index;
5357 tree var;
5358 tree cdecl;
5359 tree ctype;
5360 tree vref, dref;
5361 tree null_cond = NULL_TREE;
5363 gfc_init_block (&fnblock);
5365 if (POINTER_TYPE_P (TREE_TYPE (decl)))
5366 decl = build_fold_indirect_ref (decl);
5368 /* If this an array of derived types with allocatable components
5369 build a loop and recursively call this function. */
5370 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
5371 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5373 tmp = gfc_conv_array_data (decl);
5374 var = build_fold_indirect_ref (tmp);
5376 /* Get the number of elements - 1 and set the counter. */
5377 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5379 /* Use the descriptor for an allocatable array. Since this
5380 is a full array reference, we only need the descriptor
5381 information from dimension = rank. */
5382 tmp = get_full_array_size (&fnblock, decl, rank);
5383 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
5384 tmp, gfc_index_one_node);
5386 null_cond = gfc_conv_descriptor_data_get (decl);
5387 null_cond = fold_build2 (NE_EXPR, boolean_type_node, null_cond,
5388 build_int_cst (TREE_TYPE (null_cond), 0));
5390 else
5392 /* Otherwise use the TYPE_DOMAIN information. */
5393 tmp = array_type_nelts (TREE_TYPE (decl));
5394 tmp = fold_convert (gfc_array_index_type, tmp);
5397 /* Remember that this is, in fact, the no. of elements - 1. */
5398 nelems = gfc_evaluate_now (tmp, &fnblock);
5399 index = gfc_create_var (gfc_array_index_type, "S");
5401 /* Build the body of the loop. */
5402 gfc_init_block (&loopbody);
5404 vref = gfc_build_array_ref (var, index, NULL);
5406 if (purpose == COPY_ALLOC_COMP)
5408 tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
5409 gfc_add_expr_to_block (&fnblock, tmp);
5411 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (dest));
5412 dref = gfc_build_array_ref (tmp, index, NULL);
5413 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
5415 else
5416 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
5418 gfc_add_expr_to_block (&loopbody, tmp);
5420 /* Build the loop and return. */
5421 gfc_init_loopinfo (&loop);
5422 loop.dimen = 1;
5423 loop.from[0] = gfc_index_zero_node;
5424 loop.loopvar[0] = index;
5425 loop.to[0] = nelems;
5426 gfc_trans_scalarizing_loops (&loop, &loopbody);
5427 gfc_add_block_to_block (&fnblock, &loop.pre);
5429 tmp = gfc_finish_block (&fnblock);
5430 if (null_cond != NULL_TREE)
5431 tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
5433 return tmp;
5436 /* Otherwise, act on the components or recursively call self to
5437 act on a chain of components. */
5438 for (c = der_type->components; c; c = c->next)
5440 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
5441 && c->ts.derived->attr.alloc_comp;
5442 cdecl = c->backend_decl;
5443 ctype = TREE_TYPE (cdecl);
5445 switch (purpose)
5447 case DEALLOCATE_ALLOC_COMP:
5448 /* Do not deallocate the components of ultimate pointer
5449 components. */
5450 if (cmp_has_alloc_comps && !c->pointer)
5452 comp = fold_build3 (COMPONENT_REF, ctype,
5453 decl, cdecl, NULL_TREE);
5454 rank = c->as ? c->as->rank : 0;
5455 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5456 rank, purpose);
5457 gfc_add_expr_to_block (&fnblock, tmp);
5460 if (c->allocatable)
5462 comp = fold_build3 (COMPONENT_REF, ctype,
5463 decl, cdecl, NULL_TREE);
5464 tmp = gfc_trans_dealloc_allocated (comp);
5465 gfc_add_expr_to_block (&fnblock, tmp);
5467 break;
5469 case NULLIFY_ALLOC_COMP:
5470 if (c->pointer)
5471 continue;
5472 else if (c->allocatable)
5474 comp = fold_build3 (COMPONENT_REF, ctype,
5475 decl, cdecl, NULL_TREE);
5476 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
5478 else if (cmp_has_alloc_comps)
5480 comp = fold_build3 (COMPONENT_REF, ctype,
5481 decl, cdecl, NULL_TREE);
5482 rank = c->as ? c->as->rank : 0;
5483 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5484 rank, purpose);
5485 gfc_add_expr_to_block (&fnblock, tmp);
5487 break;
5489 case COPY_ALLOC_COMP:
5490 if (c->pointer)
5491 continue;
5493 /* We need source and destination components. */
5494 comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5495 dcmp = fold_build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
5496 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
5498 if (c->allocatable && !cmp_has_alloc_comps)
5500 tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
5501 gfc_add_expr_to_block (&fnblock, tmp);
5504 if (cmp_has_alloc_comps)
5506 rank = c->as ? c->as->rank : 0;
5507 tmp = fold_convert (TREE_TYPE (dcmp), comp);
5508 gfc_add_modify_expr (&fnblock, dcmp, tmp);
5509 tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
5510 rank, purpose);
5511 gfc_add_expr_to_block (&fnblock, tmp);
5513 break;
5515 default:
5516 gcc_unreachable ();
5517 break;
5521 return gfc_finish_block (&fnblock);
5524 /* Recursively traverse an object of derived type, generating code to
5525 nullify allocatable components. */
5527 tree
5528 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5530 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5531 NULLIFY_ALLOC_COMP);
5535 /* Recursively traverse an object of derived type, generating code to
5536 deallocate allocatable components. */
5538 tree
5539 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5541 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5542 DEALLOCATE_ALLOC_COMP);
5546 /* Recursively traverse an object of derived type, generating code to
5547 copy its allocatable components. */
5549 tree
5550 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
5552 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
5556 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
5557 Do likewise, recursively if necessary, with the allocatable components of
5558 derived types. */
5560 tree
5561 gfc_trans_deferred_array (gfc_symbol * sym, tree body)
5563 tree type;
5564 tree tmp;
5565 tree descriptor;
5566 stmtblock_t fnblock;
5567 locus loc;
5568 int rank;
5569 bool sym_has_alloc_comp;
5571 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
5572 && sym->ts.derived->attr.alloc_comp;
5574 /* Make sure the frontend gets these right. */
5575 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
5576 fatal_error ("Possible frontend bug: Deferred array size without pointer, "
5577 "allocatable attribute or derived type without allocatable "
5578 "components.");
5580 gfc_init_block (&fnblock);
5582 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
5583 || TREE_CODE (sym->backend_decl) == PARM_DECL);
5585 if (sym->ts.type == BT_CHARACTER
5586 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
5588 gfc_conv_string_length (sym->ts.cl, &fnblock);
5589 gfc_trans_vla_type_sizes (sym, &fnblock);
5592 /* Dummy and use associated variables don't need anything special. */
5593 if (sym->attr.dummy || sym->attr.use_assoc)
5595 gfc_add_expr_to_block (&fnblock, body);
5597 return gfc_finish_block (&fnblock);
5600 gfc_get_backend_locus (&loc);
5601 gfc_set_backend_locus (&sym->declared_at);
5602 descriptor = sym->backend_decl;
5604 /* Although static, derived types with default initializers and
5605 allocatable components must not be nulled wholesale; instead they
5606 are treated component by component. */
5607 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
5609 /* SAVEd variables are not freed on exit. */
5610 gfc_trans_static_array_pointer (sym);
5611 return body;
5614 /* Get the descriptor type. */
5615 type = TREE_TYPE (sym->backend_decl);
5617 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
5619 if (!sym->attr.save)
5621 rank = sym->as ? sym->as->rank : 0;
5622 tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
5623 gfc_add_expr_to_block (&fnblock, tmp);
5624 if (sym->value)
5626 tmp = gfc_init_default_dt (sym, NULL);
5627 gfc_add_expr_to_block (&fnblock, tmp);
5631 else if (!GFC_DESCRIPTOR_TYPE_P (type))
5633 /* If the backend_decl is not a descriptor, we must have a pointer
5634 to one. */
5635 descriptor = build_fold_indirect_ref (sym->backend_decl);
5636 type = TREE_TYPE (descriptor);
5639 /* NULLIFY the data pointer. */
5640 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
5641 gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
5643 gfc_add_expr_to_block (&fnblock, body);
5645 gfc_set_backend_locus (&loc);
5647 /* Allocatable arrays need to be freed when they go out of scope.
5648 The allocatable components of pointers must not be touched. */
5649 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
5650 && !sym->attr.pointer && !sym->attr.save)
5652 int rank;
5653 rank = sym->as ? sym->as->rank : 0;
5654 tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
5655 gfc_add_expr_to_block (&fnblock, tmp);
5658 if (sym->attr.allocatable && !sym->attr.save)
5660 tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
5661 gfc_add_expr_to_block (&fnblock, tmp);
5664 return gfc_finish_block (&fnblock);
5667 /************ Expression Walking Functions ******************/
5669 /* Walk a variable reference.
5671 Possible extension - multiple component subscripts.
5672 x(:,:) = foo%a(:)%b(:)
5673 Transforms to
5674 forall (i=..., j=...)
5675 x(i,j) = foo%a(j)%b(i)
5676 end forall
5677 This adds a fair amount of complexity because you need to deal with more
5678 than one ref. Maybe handle in a similar manner to vector subscripts.
5679 Maybe not worth the effort. */
5682 static gfc_ss *
5683 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
5685 gfc_ref *ref;
5686 gfc_array_ref *ar;
5687 gfc_ss *newss;
5688 gfc_ss *head;
5689 int n;
5691 for (ref = expr->ref; ref; ref = ref->next)
5692 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
5693 break;
5695 for (; ref; ref = ref->next)
5697 if (ref->type == REF_SUBSTRING)
5699 newss = gfc_get_ss ();
5700 newss->type = GFC_SS_SCALAR;
5701 newss->expr = ref->u.ss.start;
5702 newss->next = ss;
5703 ss = newss;
5705 newss = gfc_get_ss ();
5706 newss->type = GFC_SS_SCALAR;
5707 newss->expr = ref->u.ss.end;
5708 newss->next = ss;
5709 ss = newss;
5712 /* We're only interested in array sections from now on. */
5713 if (ref->type != REF_ARRAY)
5714 continue;
5716 ar = &ref->u.ar;
5717 switch (ar->type)
5719 case AR_ELEMENT:
5720 for (n = 0; n < ar->dimen; n++)
5722 newss = gfc_get_ss ();
5723 newss->type = GFC_SS_SCALAR;
5724 newss->expr = ar->start[n];
5725 newss->next = ss;
5726 ss = newss;
5728 break;
5730 case AR_FULL:
5731 newss = gfc_get_ss ();
5732 newss->type = GFC_SS_SECTION;
5733 newss->expr = expr;
5734 newss->next = ss;
5735 newss->data.info.dimen = ar->as->rank;
5736 newss->data.info.ref = ref;
5738 /* Make sure array is the same as array(:,:), this way
5739 we don't need to special case all the time. */
5740 ar->dimen = ar->as->rank;
5741 for (n = 0; n < ar->dimen; n++)
5743 newss->data.info.dim[n] = n;
5744 ar->dimen_type[n] = DIMEN_RANGE;
5746 gcc_assert (ar->start[n] == NULL);
5747 gcc_assert (ar->end[n] == NULL);
5748 gcc_assert (ar->stride[n] == NULL);
5750 ss = newss;
5751 break;
5753 case AR_SECTION:
5754 newss = gfc_get_ss ();
5755 newss->type = GFC_SS_SECTION;
5756 newss->expr = expr;
5757 newss->next = ss;
5758 newss->data.info.dimen = 0;
5759 newss->data.info.ref = ref;
5761 head = newss;
5763 /* We add SS chains for all the subscripts in the section. */
5764 for (n = 0; n < ar->dimen; n++)
5766 gfc_ss *indexss;
5768 switch (ar->dimen_type[n])
5770 case DIMEN_ELEMENT:
5771 /* Add SS for elemental (scalar) subscripts. */
5772 gcc_assert (ar->start[n]);
5773 indexss = gfc_get_ss ();
5774 indexss->type = GFC_SS_SCALAR;
5775 indexss->expr = ar->start[n];
5776 indexss->next = gfc_ss_terminator;
5777 indexss->loop_chain = gfc_ss_terminator;
5778 newss->data.info.subscript[n] = indexss;
5779 break;
5781 case DIMEN_RANGE:
5782 /* We don't add anything for sections, just remember this
5783 dimension for later. */
5784 newss->data.info.dim[newss->data.info.dimen] = n;
5785 newss->data.info.dimen++;
5786 break;
5788 case DIMEN_VECTOR:
5789 /* Create a GFC_SS_VECTOR index in which we can store
5790 the vector's descriptor. */
5791 indexss = gfc_get_ss ();
5792 indexss->type = GFC_SS_VECTOR;
5793 indexss->expr = ar->start[n];
5794 indexss->next = gfc_ss_terminator;
5795 indexss->loop_chain = gfc_ss_terminator;
5796 newss->data.info.subscript[n] = indexss;
5797 newss->data.info.dim[newss->data.info.dimen] = n;
5798 newss->data.info.dimen++;
5799 break;
5801 default:
5802 /* We should know what sort of section it is by now. */
5803 gcc_unreachable ();
5806 /* We should have at least one non-elemental dimension. */
5807 gcc_assert (newss->data.info.dimen > 0);
5808 ss = newss;
5809 break;
5811 default:
5812 /* We should know what sort of section it is by now. */
5813 gcc_unreachable ();
5817 return ss;
5821 /* Walk an expression operator. If only one operand of a binary expression is
5822 scalar, we must also add the scalar term to the SS chain. */
5824 static gfc_ss *
5825 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
5827 gfc_ss *head;
5828 gfc_ss *head2;
5829 gfc_ss *newss;
5831 head = gfc_walk_subexpr (ss, expr->value.op.op1);
5832 if (expr->value.op.op2 == NULL)
5833 head2 = head;
5834 else
5835 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
5837 /* All operands are scalar. Pass back and let the caller deal with it. */
5838 if (head2 == ss)
5839 return head2;
5841 /* All operands require scalarization. */
5842 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
5843 return head2;
5845 /* One of the operands needs scalarization, the other is scalar.
5846 Create a gfc_ss for the scalar expression. */
5847 newss = gfc_get_ss ();
5848 newss->type = GFC_SS_SCALAR;
5849 if (head == ss)
5851 /* First operand is scalar. We build the chain in reverse order, so
5852 add the scarar SS after the second operand. */
5853 head = head2;
5854 while (head && head->next != ss)
5855 head = head->next;
5856 /* Check we haven't somehow broken the chain. */
5857 gcc_assert (head);
5858 newss->next = ss;
5859 head->next = newss;
5860 newss->expr = expr->value.op.op1;
5862 else /* head2 == head */
5864 gcc_assert (head2 == head);
5865 /* Second operand is scalar. */
5866 newss->next = head2;
5867 head2 = newss;
5868 newss->expr = expr->value.op.op2;
5871 return head2;
5875 /* Reverse a SS chain. */
5877 gfc_ss *
5878 gfc_reverse_ss (gfc_ss * ss)
5880 gfc_ss *next;
5881 gfc_ss *head;
5883 gcc_assert (ss != NULL);
5885 head = gfc_ss_terminator;
5886 while (ss != gfc_ss_terminator)
5888 next = ss->next;
5889 /* Check we didn't somehow break the chain. */
5890 gcc_assert (next != NULL);
5891 ss->next = head;
5892 head = ss;
5893 ss = next;
5896 return (head);
5900 /* Walk the arguments of an elemental function. */
5902 gfc_ss *
5903 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
5904 gfc_ss_type type)
5906 int scalar;
5907 gfc_ss *head;
5908 gfc_ss *tail;
5909 gfc_ss *newss;
5911 head = gfc_ss_terminator;
5912 tail = NULL;
5913 scalar = 1;
5914 for (; arg; arg = arg->next)
5916 if (!arg->expr)
5917 continue;
5919 newss = gfc_walk_subexpr (head, arg->expr);
5920 if (newss == head)
5922 /* Scalar argument. */
5923 newss = gfc_get_ss ();
5924 newss->type = type;
5925 newss->expr = arg->expr;
5926 newss->next = head;
5928 else
5929 scalar = 0;
5931 head = newss;
5932 if (!tail)
5934 tail = head;
5935 while (tail->next != gfc_ss_terminator)
5936 tail = tail->next;
5940 if (scalar)
5942 /* If all the arguments are scalar we don't need the argument SS. */
5943 gfc_free_ss_chain (head);
5944 /* Pass it back. */
5945 return ss;
5948 /* Add it onto the existing chain. */
5949 tail->next = ss;
5950 return head;
5954 /* Walk a function call. Scalar functions are passed back, and taken out of
5955 scalarization loops. For elemental functions we walk their arguments.
5956 The result of functions returning arrays is stored in a temporary outside
5957 the loop, so that the function is only called once. Hence we do not need
5958 to walk their arguments. */
5960 static gfc_ss *
5961 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
5963 gfc_ss *newss;
5964 gfc_intrinsic_sym *isym;
5965 gfc_symbol *sym;
5967 isym = expr->value.function.isym;
5969 /* Handle intrinsic functions separately. */
5970 if (isym)
5971 return gfc_walk_intrinsic_function (ss, expr, isym);
5973 sym = expr->value.function.esym;
5974 if (!sym)
5975 sym = expr->symtree->n.sym;
5977 /* A function that returns arrays. */
5978 if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
5980 newss = gfc_get_ss ();
5981 newss->type = GFC_SS_FUNCTION;
5982 newss->expr = expr;
5983 newss->next = ss;
5984 newss->data.info.dimen = expr->rank;
5985 return newss;
5988 /* Walk the parameters of an elemental function. For now we always pass
5989 by reference. */
5990 if (sym->attr.elemental)
5991 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
5992 GFC_SS_REFERENCE);
5994 /* Scalar functions are OK as these are evaluated outside the scalarization
5995 loop. Pass back and let the caller deal with it. */
5996 return ss;
6000 /* An array temporary is constructed for array constructors. */
6002 static gfc_ss *
6003 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
6005 gfc_ss *newss;
6006 int n;
6008 newss = gfc_get_ss ();
6009 newss->type = GFC_SS_CONSTRUCTOR;
6010 newss->expr = expr;
6011 newss->next = ss;
6012 newss->data.info.dimen = expr->rank;
6013 for (n = 0; n < expr->rank; n++)
6014 newss->data.info.dim[n] = n;
6016 return newss;
6020 /* Walk an expression. Add walked expressions to the head of the SS chain.
6021 A wholly scalar expression will not be added. */
6023 static gfc_ss *
6024 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
6026 gfc_ss *head;
6028 switch (expr->expr_type)
6030 case EXPR_VARIABLE:
6031 head = gfc_walk_variable_expr (ss, expr);
6032 return head;
6034 case EXPR_OP:
6035 head = gfc_walk_op_expr (ss, expr);
6036 return head;
6038 case EXPR_FUNCTION:
6039 head = gfc_walk_function_expr (ss, expr);
6040 return head;
6042 case EXPR_CONSTANT:
6043 case EXPR_NULL:
6044 case EXPR_STRUCTURE:
6045 /* Pass back and let the caller deal with it. */
6046 break;
6048 case EXPR_ARRAY:
6049 head = gfc_walk_array_constructor (ss, expr);
6050 return head;
6052 case EXPR_SUBSTRING:
6053 /* Pass back and let the caller deal with it. */
6054 break;
6056 default:
6057 internal_error ("bad expression type during walk (%d)",
6058 expr->expr_type);
6060 return ss;
6064 /* Entry point for expression walking.
6065 A return value equal to the passed chain means this is
6066 a scalar expression. It is up to the caller to take whatever action is
6067 necessary to translate these. */
6069 gfc_ss *
6070 gfc_walk_expr (gfc_expr * expr)
6072 gfc_ss *res;
6074 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
6075 return gfc_reverse_ss (res);