gcc/java/
[official-gcc.git] / gcc / fortran / trans-array.c
blobcf38fc371beedb4e82d8dcc7d7e05721c6217603
1 /* Array translation routines
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
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 subscripts 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 "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. */
166 void
167 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
169 tree field, type, t;
171 type = TREE_TYPE (desc);
172 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
174 field = TYPE_FIELDS (type);
175 gcc_assert (DATA_FIELD == 0);
177 t = fold_build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
178 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
182 /* This provides address access to the data field. This should only be
183 used by array allocation, passing this on to the runtime. */
185 tree
186 gfc_conv_descriptor_data_addr (tree desc)
188 tree field, type, t;
190 type = TREE_TYPE (desc);
191 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
193 field = TYPE_FIELDS (type);
194 gcc_assert (DATA_FIELD == 0);
196 t = fold_build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
197 return gfc_build_addr_expr (NULL_TREE, t);
200 static tree
201 gfc_conv_descriptor_offset (tree desc)
203 tree type;
204 tree field;
206 type = TREE_TYPE (desc);
207 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
209 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
210 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
212 return fold_build3 (COMPONENT_REF, TREE_TYPE (field),
213 desc, field, NULL_TREE);
216 tree
217 gfc_conv_descriptor_offset_get (tree desc)
219 return gfc_conv_descriptor_offset (desc);
222 void
223 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
224 tree value)
226 tree t = gfc_conv_descriptor_offset (desc);
227 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
231 tree
232 gfc_conv_descriptor_dtype (tree desc)
234 tree field;
235 tree type;
237 type = TREE_TYPE (desc);
238 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
240 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
241 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
243 return fold_build3 (COMPONENT_REF, TREE_TYPE (field),
244 desc, field, NULL_TREE);
247 static tree
248 gfc_conv_descriptor_dimension (tree desc, tree dim)
250 tree field;
251 tree type;
252 tree tmp;
254 type = TREE_TYPE (desc);
255 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
257 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
258 gcc_assert (field != NULL_TREE
259 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
260 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
262 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
263 desc, field, NULL_TREE);
264 tmp = gfc_build_array_ref (tmp, dim, NULL);
265 return tmp;
268 static tree
269 gfc_conv_descriptor_stride (tree desc, tree dim)
271 tree tmp;
272 tree field;
274 tmp = gfc_conv_descriptor_dimension (desc, dim);
275 field = TYPE_FIELDS (TREE_TYPE (tmp));
276 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
277 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
279 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
280 tmp, field, NULL_TREE);
281 return tmp;
284 tree
285 gfc_conv_descriptor_stride_get (tree desc, tree dim)
287 return gfc_conv_descriptor_stride (desc, dim);
290 void
291 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
292 tree dim, tree value)
294 tree t = gfc_conv_descriptor_stride (desc, dim);
295 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
298 static tree
299 gfc_conv_descriptor_lbound (tree desc, tree dim)
301 tree tmp;
302 tree field;
304 tmp = gfc_conv_descriptor_dimension (desc, dim);
305 field = TYPE_FIELDS (TREE_TYPE (tmp));
306 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
307 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
309 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
310 tmp, field, NULL_TREE);
311 return tmp;
314 tree
315 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
317 return gfc_conv_descriptor_lbound (desc, dim);
320 void
321 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
322 tree dim, tree value)
324 tree t = gfc_conv_descriptor_lbound (desc, dim);
325 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
328 static tree
329 gfc_conv_descriptor_ubound (tree desc, tree dim)
331 tree tmp;
332 tree field;
334 tmp = gfc_conv_descriptor_dimension (desc, dim);
335 field = TYPE_FIELDS (TREE_TYPE (tmp));
336 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
337 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
339 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
340 tmp, field, NULL_TREE);
341 return tmp;
344 tree
345 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
347 return gfc_conv_descriptor_ubound (desc, dim);
350 void
351 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
352 tree dim, tree value)
354 tree t = gfc_conv_descriptor_ubound (desc, dim);
355 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
358 /* Build a null array descriptor constructor. */
360 tree
361 gfc_build_null_descriptor (tree type)
363 tree field;
364 tree tmp;
366 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
367 gcc_assert (DATA_FIELD == 0);
368 field = TYPE_FIELDS (type);
370 /* Set a NULL data pointer. */
371 tmp = build_constructor_single (type, field, null_pointer_node);
372 TREE_CONSTANT (tmp) = 1;
373 /* All other fields are ignored. */
375 return tmp;
379 /* Cleanup those #defines. */
381 #undef DATA_FIELD
382 #undef OFFSET_FIELD
383 #undef DTYPE_FIELD
384 #undef DIMENSION_FIELD
385 #undef STRIDE_SUBFIELD
386 #undef LBOUND_SUBFIELD
387 #undef UBOUND_SUBFIELD
390 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
391 flags & 1 = Main loop body.
392 flags & 2 = temp copy loop. */
394 void
395 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
397 for (; ss != gfc_ss_terminator; ss = ss->next)
398 ss->useflags = flags;
401 static void gfc_free_ss (gfc_ss *);
404 /* Free a gfc_ss chain. */
406 static void
407 gfc_free_ss_chain (gfc_ss * ss)
409 gfc_ss *next;
411 while (ss != gfc_ss_terminator)
413 gcc_assert (ss != NULL);
414 next = ss->next;
415 gfc_free_ss (ss);
416 ss = next;
421 /* Free a SS. */
423 static void
424 gfc_free_ss (gfc_ss * ss)
426 int n;
428 switch (ss->type)
430 case GFC_SS_SECTION:
431 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
433 if (ss->data.info.subscript[n])
434 gfc_free_ss_chain (ss->data.info.subscript[n]);
436 break;
438 default:
439 break;
442 gfc_free (ss);
446 /* Free all the SS associated with a loop. */
448 void
449 gfc_cleanup_loop (gfc_loopinfo * loop)
451 gfc_ss *ss;
452 gfc_ss *next;
454 ss = loop->ss;
455 while (ss != gfc_ss_terminator)
457 gcc_assert (ss != NULL);
458 next = ss->loop_chain;
459 gfc_free_ss (ss);
460 ss = next;
465 /* Associate a SS chain with a loop. */
467 void
468 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
470 gfc_ss *ss;
472 if (head == gfc_ss_terminator)
473 return;
475 ss = head;
476 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
478 if (ss->next == gfc_ss_terminator)
479 ss->loop_chain = loop->ss;
480 else
481 ss->loop_chain = ss->next;
483 gcc_assert (ss == gfc_ss_terminator);
484 loop->ss = head;
488 /* Generate an initializer for a static pointer or allocatable array. */
490 void
491 gfc_trans_static_array_pointer (gfc_symbol * sym)
493 tree type;
495 gcc_assert (TREE_STATIC (sym->backend_decl));
496 /* Just zero the data member. */
497 type = TREE_TYPE (sym->backend_decl);
498 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
502 /* If the bounds of SE's loop have not yet been set, see if they can be
503 determined from array spec AS, which is the array spec of a called
504 function. MAPPING maps the callee's dummy arguments to the values
505 that the caller is passing. Add any initialization and finalization
506 code to SE. */
508 void
509 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
510 gfc_se * se, gfc_array_spec * as)
512 int n, dim;
513 gfc_se tmpse;
514 tree lower;
515 tree upper;
516 tree tmp;
518 if (as && as->type == AS_EXPLICIT)
519 for (dim = 0; dim < se->loop->dimen; dim++)
521 n = se->loop->order[dim];
522 if (se->loop->to[n] == NULL_TREE)
524 /* Evaluate the lower bound. */
525 gfc_init_se (&tmpse, NULL);
526 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
527 gfc_add_block_to_block (&se->pre, &tmpse.pre);
528 gfc_add_block_to_block (&se->post, &tmpse.post);
529 lower = fold_convert (gfc_array_index_type, tmpse.expr);
531 /* ...and the upper bound. */
532 gfc_init_se (&tmpse, NULL);
533 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
534 gfc_add_block_to_block (&se->pre, &tmpse.pre);
535 gfc_add_block_to_block (&se->post, &tmpse.post);
536 upper = fold_convert (gfc_array_index_type, tmpse.expr);
538 /* Set the upper bound of the loop to UPPER - LOWER. */
539 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
540 tmp = gfc_evaluate_now (tmp, &se->pre);
541 se->loop->to[n] = tmp;
547 /* Generate code to allocate an array temporary, or create a variable to
548 hold the data. If size is NULL, zero the descriptor so that the
549 callee will allocate the array. If DEALLOC is true, also generate code to
550 free the array afterwards.
552 If INITIAL is not NULL, it is packed using internal_pack and the result used
553 as data instead of allocating a fresh, unitialized area of memory.
555 Initialization code is added to PRE and finalization code to POST.
556 DYNAMIC is true if the caller may want to extend the array later
557 using realloc. This prevents us from putting the array on the stack. */
559 static void
560 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
561 gfc_ss_info * info, tree size, tree nelem,
562 tree initial, bool dynamic, bool dealloc)
564 tree tmp;
565 tree desc;
566 bool onstack;
568 desc = info->descriptor;
569 info->offset = gfc_index_zero_node;
570 if (size == NULL_TREE || integer_zerop (size))
572 /* A callee allocated array. */
573 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
574 onstack = FALSE;
576 else
578 /* Allocate the temporary. */
579 onstack = !dynamic && initial == NULL_TREE
580 && gfc_can_put_var_on_stack (size);
582 if (onstack)
584 /* Make a temporary variable to hold the data. */
585 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (nelem), nelem,
586 gfc_index_one_node);
587 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
588 tmp);
589 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
590 tmp);
591 tmp = gfc_create_var (tmp, "A");
592 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
593 gfc_conv_descriptor_data_set (pre, desc, tmp);
595 else
597 /* Allocate memory to hold the data or call internal_pack. */
598 if (initial == NULL_TREE)
600 tmp = gfc_call_malloc (pre, NULL, size);
601 tmp = gfc_evaluate_now (tmp, pre);
603 else
605 tree packed;
606 tree source_data;
607 tree was_packed;
608 stmtblock_t do_copying;
610 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
611 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
612 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
613 tmp = gfc_get_element_type (tmp);
614 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
615 packed = gfc_create_var (build_pointer_type (tmp), "data");
617 tmp = build_call_expr (gfor_fndecl_in_pack, 1, initial);
618 tmp = fold_convert (TREE_TYPE (packed), tmp);
619 gfc_add_modify (pre, packed, tmp);
621 tmp = build_fold_indirect_ref (initial);
622 source_data = gfc_conv_descriptor_data_get (tmp);
624 /* internal_pack may return source->data without any allocation
625 or copying if it is already packed. If that's the case, we
626 need to allocate and copy manually. */
628 gfc_start_block (&do_copying);
629 tmp = gfc_call_malloc (&do_copying, NULL, size);
630 tmp = fold_convert (TREE_TYPE (packed), tmp);
631 gfc_add_modify (&do_copying, packed, tmp);
632 tmp = gfc_build_memcpy_call (packed, source_data, size);
633 gfc_add_expr_to_block (&do_copying, tmp);
635 was_packed = fold_build2 (EQ_EXPR, boolean_type_node,
636 packed, source_data);
637 tmp = gfc_finish_block (&do_copying);
638 tmp = build3_v (COND_EXPR, was_packed, tmp,
639 build_empty_stmt (input_location));
640 gfc_add_expr_to_block (pre, tmp);
642 tmp = fold_convert (pvoid_type_node, packed);
645 gfc_conv_descriptor_data_set (pre, desc, tmp);
648 info->data = gfc_conv_descriptor_data_get (desc);
650 /* The offset is zero because we create temporaries with a zero
651 lower bound. */
652 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
654 if (dealloc && !onstack)
656 /* Free the temporary. */
657 tmp = gfc_conv_descriptor_data_get (desc);
658 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
659 gfc_add_expr_to_block (post, tmp);
664 /* Generate code to create and initialize the descriptor for a temporary
665 array. This is used for both temporaries needed by the scalarizer, and
666 functions returning arrays. Adjusts the loop variables to be
667 zero-based, and calculates the loop bounds for callee allocated arrays.
668 Allocate the array unless it's callee allocated (we have a callee
669 allocated array if 'callee_alloc' is true, or if loop->to[n] is
670 NULL_TREE for any n). Also fills in the descriptor, data and offset
671 fields of info if known. Returns the size of the array, or NULL for a
672 callee allocated array.
674 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
675 gfc_trans_allocate_array_storage.
678 tree
679 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
680 gfc_loopinfo * loop, gfc_ss_info * info,
681 tree eltype, tree initial, bool dynamic,
682 bool dealloc, bool callee_alloc, locus * where)
684 tree type;
685 tree desc;
686 tree tmp;
687 tree size;
688 tree nelem;
689 tree cond;
690 tree or_expr;
691 int n;
692 int dim;
694 gcc_assert (info->dimen > 0);
696 if (gfc_option.warn_array_temp && where)
697 gfc_warning ("Creating array temporary at %L", where);
699 /* Set the lower bound to zero. */
700 for (dim = 0; dim < info->dimen; dim++)
702 n = loop->order[dim];
703 /* Callee allocated arrays may not have a known bound yet. */
704 if (loop->to[n])
705 loop->to[n] = gfc_evaluate_now (fold_build2 (MINUS_EXPR,
706 gfc_array_index_type,
707 loop->to[n], loop->from[n]), pre);
708 loop->from[n] = gfc_index_zero_node;
710 info->delta[dim] = gfc_index_zero_node;
711 info->start[dim] = gfc_index_zero_node;
712 info->end[dim] = gfc_index_zero_node;
713 info->stride[dim] = gfc_index_one_node;
714 info->dim[dim] = dim;
717 /* Initialize the descriptor. */
718 type =
719 gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1,
720 GFC_ARRAY_UNKNOWN);
721 desc = gfc_create_var (type, "atmp");
722 GFC_DECL_PACKED_ARRAY (desc) = 1;
724 info->descriptor = desc;
725 size = gfc_index_one_node;
727 /* Fill in the array dtype. */
728 tmp = gfc_conv_descriptor_dtype (desc);
729 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
732 Fill in the bounds and stride. This is a packed array, so:
734 size = 1;
735 for (n = 0; n < rank; n++)
737 stride[n] = size
738 delta = ubound[n] + 1 - lbound[n];
739 size = size * delta;
741 size = size * sizeof(element);
744 or_expr = NULL_TREE;
746 /* If there is at least one null loop->to[n], it is a callee allocated
747 array. */
748 for (n = 0; n < info->dimen; n++)
749 if (loop->to[n] == NULL_TREE)
751 size = NULL_TREE;
752 break;
755 for (n = 0; n < info->dimen; n++)
757 if (size == NULL_TREE)
759 /* For a callee allocated array express the loop bounds in terms
760 of the descriptor fields. */
761 tmp =
762 fold_build2 (MINUS_EXPR, gfc_array_index_type,
763 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]),
764 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]));
765 loop->to[n] = tmp;
766 continue;
769 /* Store the stride and bound components in the descriptor. */
770 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
772 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
773 gfc_index_zero_node);
775 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], loop->to[n]);
777 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
778 loop->to[n], gfc_index_one_node);
780 /* Check whether the size for this dimension is negative. */
781 cond = fold_build2 (LE_EXPR, boolean_type_node, tmp,
782 gfc_index_zero_node);
783 cond = gfc_evaluate_now (cond, pre);
785 if (n == 0)
786 or_expr = cond;
787 else
788 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
790 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
791 size = gfc_evaluate_now (size, pre);
794 /* Get the size of the array. */
796 if (size && !callee_alloc)
798 /* If or_expr is true, then the extent in at least one
799 dimension is zero and the size is set to zero. */
800 size = fold_build3 (COND_EXPR, gfc_array_index_type,
801 or_expr, gfc_index_zero_node, size);
803 nelem = size;
804 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
805 fold_convert (gfc_array_index_type,
806 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
808 else
810 nelem = size;
811 size = NULL_TREE;
814 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
815 dynamic, dealloc);
817 if (info->dimen > loop->temp_dim)
818 loop->temp_dim = info->dimen;
820 return size;
824 /* Generate code to transpose array EXPR by creating a new descriptor
825 in which the dimension specifications have been reversed. */
827 void
828 gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
830 tree dest, src, dest_index, src_index;
831 gfc_loopinfo *loop;
832 gfc_ss_info *dest_info, *src_info;
833 gfc_ss *dest_ss, *src_ss;
834 gfc_se src_se;
835 int n;
837 loop = se->loop;
839 src_ss = gfc_walk_expr (expr);
840 dest_ss = se->ss;
842 src_info = &src_ss->data.info;
843 dest_info = &dest_ss->data.info;
844 gcc_assert (dest_info->dimen == 2);
845 gcc_assert (src_info->dimen == 2);
847 /* Get a descriptor for EXPR. */
848 gfc_init_se (&src_se, NULL);
849 gfc_conv_expr_descriptor (&src_se, expr, src_ss);
850 gfc_add_block_to_block (&se->pre, &src_se.pre);
851 gfc_add_block_to_block (&se->post, &src_se.post);
852 src = src_se.expr;
854 /* Allocate a new descriptor for the return value. */
855 dest = gfc_create_var (TREE_TYPE (src), "atmp");
856 dest_info->descriptor = dest;
857 se->expr = dest;
859 /* Copy across the dtype field. */
860 gfc_add_modify (&se->pre,
861 gfc_conv_descriptor_dtype (dest),
862 gfc_conv_descriptor_dtype (src));
864 /* Copy the dimension information, renumbering dimension 1 to 0 and
865 0 to 1. */
866 for (n = 0; n < 2; n++)
868 dest_info->delta[n] = gfc_index_zero_node;
869 dest_info->start[n] = gfc_index_zero_node;
870 dest_info->end[n] = gfc_index_zero_node;
871 dest_info->stride[n] = gfc_index_one_node;
872 dest_info->dim[n] = n;
874 dest_index = gfc_rank_cst[n];
875 src_index = gfc_rank_cst[1 - n];
877 gfc_conv_descriptor_stride_set (&se->pre, dest, dest_index,
878 gfc_conv_descriptor_stride_get (src, src_index));
880 gfc_conv_descriptor_lbound_set (&se->pre, dest, dest_index,
881 gfc_conv_descriptor_lbound_get (src, src_index));
883 gfc_conv_descriptor_ubound_set (&se->pre, dest, dest_index,
884 gfc_conv_descriptor_ubound_get (src, src_index));
886 if (!loop->to[n])
888 gcc_assert (integer_zerop (loop->from[n]));
889 loop->to[n] =
890 fold_build2 (MINUS_EXPR, gfc_array_index_type,
891 gfc_conv_descriptor_ubound_get (dest, dest_index),
892 gfc_conv_descriptor_lbound_get (dest, dest_index));
896 /* Copy the data pointer. */
897 dest_info->data = gfc_conv_descriptor_data_get (src);
898 gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);
900 /* Copy the offset. This is not changed by transposition; the top-left
901 element is still at the same offset as before, except where the loop
902 starts at zero. */
903 if (!integer_zerop (loop->from[0]))
904 dest_info->offset = gfc_conv_descriptor_offset_get (src);
905 else
906 dest_info->offset = gfc_index_zero_node;
908 gfc_conv_descriptor_offset_set (&se->pre, dest,
909 dest_info->offset);
911 if (dest_info->dimen > loop->temp_dim)
912 loop->temp_dim = dest_info->dimen;
916 /* Return the number of iterations in a loop that starts at START,
917 ends at END, and has step STEP. */
919 static tree
920 gfc_get_iteration_count (tree start, tree end, tree step)
922 tree tmp;
923 tree type;
925 type = TREE_TYPE (step);
926 tmp = fold_build2 (MINUS_EXPR, type, end, start);
927 tmp = fold_build2 (FLOOR_DIV_EXPR, type, tmp, step);
928 tmp = fold_build2 (PLUS_EXPR, type, tmp, build_int_cst (type, 1));
929 tmp = fold_build2 (MAX_EXPR, type, tmp, build_int_cst (type, 0));
930 return fold_convert (gfc_array_index_type, tmp);
934 /* Extend the data in array DESC by EXTRA elements. */
936 static void
937 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
939 tree arg0, arg1;
940 tree tmp;
941 tree size;
942 tree ubound;
944 if (integer_zerop (extra))
945 return;
947 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
949 /* Add EXTRA to the upper bound. */
950 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
951 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
953 /* Get the value of the current data pointer. */
954 arg0 = gfc_conv_descriptor_data_get (desc);
956 /* Calculate the new array size. */
957 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
958 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
959 ubound, gfc_index_one_node);
960 arg1 = fold_build2 (MULT_EXPR, size_type_node,
961 fold_convert (size_type_node, tmp),
962 fold_convert (size_type_node, size));
964 /* Call the realloc() function. */
965 tmp = gfc_call_realloc (pblock, arg0, arg1);
966 gfc_conv_descriptor_data_set (pblock, desc, tmp);
970 /* Return true if the bounds of iterator I can only be determined
971 at run time. */
973 static inline bool
974 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
976 return (i->start->expr_type != EXPR_CONSTANT
977 || i->end->expr_type != EXPR_CONSTANT
978 || i->step->expr_type != EXPR_CONSTANT);
982 /* Split the size of constructor element EXPR into the sum of two terms,
983 one of which can be determined at compile time and one of which must
984 be calculated at run time. Set *SIZE to the former and return true
985 if the latter might be nonzero. */
987 static bool
988 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
990 if (expr->expr_type == EXPR_ARRAY)
991 return gfc_get_array_constructor_size (size, expr->value.constructor);
992 else if (expr->rank > 0)
994 /* Calculate everything at run time. */
995 mpz_set_ui (*size, 0);
996 return true;
998 else
1000 /* A single element. */
1001 mpz_set_ui (*size, 1);
1002 return false;
1007 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1008 of array constructor C. */
1010 static bool
1011 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
1013 gfc_iterator *i;
1014 mpz_t val;
1015 mpz_t len;
1016 bool dynamic;
1018 mpz_set_ui (*size, 0);
1019 mpz_init (len);
1020 mpz_init (val);
1022 dynamic = false;
1023 for (; c; c = c->next)
1025 i = c->iterator;
1026 if (i && gfc_iterator_has_dynamic_bounds (i))
1027 dynamic = true;
1028 else
1030 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1031 if (i)
1033 /* Multiply the static part of the element size by the
1034 number of iterations. */
1035 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1036 mpz_fdiv_q (val, val, i->step->value.integer);
1037 mpz_add_ui (val, val, 1);
1038 if (mpz_sgn (val) > 0)
1039 mpz_mul (len, len, val);
1040 else
1041 mpz_set_ui (len, 0);
1043 mpz_add (*size, *size, len);
1046 mpz_clear (len);
1047 mpz_clear (val);
1048 return dynamic;
1052 /* Make sure offset is a variable. */
1054 static void
1055 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1056 tree * offsetvar)
1058 /* We should have already created the offset variable. We cannot
1059 create it here because we may be in an inner scope. */
1060 gcc_assert (*offsetvar != NULL_TREE);
1061 gfc_add_modify (pblock, *offsetvar, *poffset);
1062 *poffset = *offsetvar;
1063 TREE_USED (*offsetvar) = 1;
1067 /* Variables needed for bounds-checking. */
1068 static bool first_len;
1069 static tree first_len_val;
1070 static bool typespec_chararray_ctor;
1072 static void
1073 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1074 tree offset, gfc_se * se, gfc_expr * expr)
1076 tree tmp;
1078 gfc_conv_expr (se, expr);
1080 /* Store the value. */
1081 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
1082 tmp = gfc_build_array_ref (tmp, offset, NULL);
1084 if (expr->ts.type == BT_CHARACTER)
1086 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1087 tree esize;
1089 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1090 esize = fold_convert (gfc_charlen_type_node, esize);
1091 esize = fold_build2 (TRUNC_DIV_EXPR, gfc_charlen_type_node, esize,
1092 build_int_cst (gfc_charlen_type_node,
1093 gfc_character_kinds[i].bit_size / 8));
1095 gfc_conv_string_parameter (se);
1096 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1098 /* The temporary is an array of pointers. */
1099 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1100 gfc_add_modify (&se->pre, tmp, se->expr);
1102 else
1104 /* The temporary is an array of string values. */
1105 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1106 /* We know the temporary and the value will be the same length,
1107 so can use memcpy. */
1108 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1109 se->string_length, se->expr, expr->ts.kind);
1111 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1113 if (first_len)
1115 gfc_add_modify (&se->pre, first_len_val,
1116 se->string_length);
1117 first_len = false;
1119 else
1121 /* Verify that all constructor elements are of the same
1122 length. */
1123 tree cond = fold_build2 (NE_EXPR, boolean_type_node,
1124 first_len_val, se->string_length);
1125 gfc_trans_runtime_check
1126 (true, false, cond, &se->pre, &expr->where,
1127 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1128 fold_convert (long_integer_type_node, first_len_val),
1129 fold_convert (long_integer_type_node, se->string_length));
1133 else
1135 /* TODO: Should the frontend already have done this conversion? */
1136 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1137 gfc_add_modify (&se->pre, tmp, se->expr);
1140 gfc_add_block_to_block (pblock, &se->pre);
1141 gfc_add_block_to_block (pblock, &se->post);
1145 /* Add the contents of an array to the constructor. DYNAMIC is as for
1146 gfc_trans_array_constructor_value. */
1148 static void
1149 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1150 tree type ATTRIBUTE_UNUSED,
1151 tree desc, gfc_expr * expr,
1152 tree * poffset, tree * offsetvar,
1153 bool dynamic)
1155 gfc_se se;
1156 gfc_ss *ss;
1157 gfc_loopinfo loop;
1158 stmtblock_t body;
1159 tree tmp;
1160 tree size;
1161 int n;
1163 /* We need this to be a variable so we can increment it. */
1164 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1166 gfc_init_se (&se, NULL);
1168 /* Walk the array expression. */
1169 ss = gfc_walk_expr (expr);
1170 gcc_assert (ss != gfc_ss_terminator);
1172 /* Initialize the scalarizer. */
1173 gfc_init_loopinfo (&loop);
1174 gfc_add_ss_to_loop (&loop, ss);
1176 /* Initialize the loop. */
1177 gfc_conv_ss_startstride (&loop);
1178 gfc_conv_loop_setup (&loop, &expr->where);
1180 /* Make sure the constructed array has room for the new data. */
1181 if (dynamic)
1183 /* Set SIZE to the total number of elements in the subarray. */
1184 size = gfc_index_one_node;
1185 for (n = 0; n < loop.dimen; n++)
1187 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1188 gfc_index_one_node);
1189 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1192 /* Grow the constructed array by SIZE elements. */
1193 gfc_grow_array (&loop.pre, desc, size);
1196 /* Make the loop body. */
1197 gfc_mark_ss_chain_used (ss, 1);
1198 gfc_start_scalarized_body (&loop, &body);
1199 gfc_copy_loopinfo_to_se (&se, &loop);
1200 se.ss = ss;
1202 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1203 gcc_assert (se.ss == gfc_ss_terminator);
1205 /* Increment the offset. */
1206 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1207 *poffset, gfc_index_one_node);
1208 gfc_add_modify (&body, *poffset, tmp);
1210 /* Finish the loop. */
1211 gfc_trans_scalarizing_loops (&loop, &body);
1212 gfc_add_block_to_block (&loop.pre, &loop.post);
1213 tmp = gfc_finish_block (&loop.pre);
1214 gfc_add_expr_to_block (pblock, tmp);
1216 gfc_cleanup_loop (&loop);
1220 /* Assign the values to the elements of an array constructor. DYNAMIC
1221 is true if descriptor DESC only contains enough data for the static
1222 size calculated by gfc_get_array_constructor_size. When true, memory
1223 for the dynamic parts must be allocated using realloc. */
1225 static void
1226 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1227 tree desc, gfc_constructor * c,
1228 tree * poffset, tree * offsetvar,
1229 bool dynamic)
1231 tree tmp;
1232 stmtblock_t body;
1233 gfc_se se;
1234 mpz_t size;
1236 tree shadow_loopvar = NULL_TREE;
1237 gfc_saved_var saved_loopvar;
1239 mpz_init (size);
1240 for (; c; c = c->next)
1242 /* If this is an iterator or an array, the offset must be a variable. */
1243 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1244 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1246 /* Shadowing the iterator avoids changing its value and saves us from
1247 keeping track of it. Further, it makes sure that there's always a
1248 backend-decl for the symbol, even if there wasn't one before,
1249 e.g. in the case of an iterator that appears in a specification
1250 expression in an interface mapping. */
1251 if (c->iterator)
1253 gfc_symbol *sym = c->iterator->var->symtree->n.sym;
1254 tree type = gfc_typenode_for_spec (&sym->ts);
1256 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1257 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1260 gfc_start_block (&body);
1262 if (c->expr->expr_type == EXPR_ARRAY)
1264 /* Array constructors can be nested. */
1265 gfc_trans_array_constructor_value (&body, type, desc,
1266 c->expr->value.constructor,
1267 poffset, offsetvar, dynamic);
1269 else if (c->expr->rank > 0)
1271 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1272 poffset, offsetvar, dynamic);
1274 else
1276 /* This code really upsets the gimplifier so don't bother for now. */
1277 gfc_constructor *p;
1278 HOST_WIDE_INT n;
1279 HOST_WIDE_INT size;
1281 p = c;
1282 n = 0;
1283 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1285 p = p->next;
1286 n++;
1288 if (n < 4)
1290 /* Scalar values. */
1291 gfc_init_se (&se, NULL);
1292 gfc_trans_array_ctor_element (&body, desc, *poffset,
1293 &se, c->expr);
1295 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1296 *poffset, gfc_index_one_node);
1298 else
1300 /* Collect multiple scalar constants into a constructor. */
1301 tree list;
1302 tree init;
1303 tree bound;
1304 tree tmptype;
1305 HOST_WIDE_INT idx = 0;
1307 p = c;
1308 list = NULL_TREE;
1309 /* Count the number of consecutive scalar constants. */
1310 while (p && !(p->iterator
1311 || p->expr->expr_type != EXPR_CONSTANT))
1313 gfc_init_se (&se, NULL);
1314 gfc_conv_constant (&se, p->expr);
1316 if (c->expr->ts.type != BT_CHARACTER)
1317 se.expr = fold_convert (type, se.expr);
1318 /* For constant character array constructors we build
1319 an array of pointers. */
1320 else if (POINTER_TYPE_P (type))
1321 se.expr = gfc_build_addr_expr
1322 (gfc_get_pchar_type (p->expr->ts.kind),
1323 se.expr);
1325 list = tree_cons (build_int_cst (gfc_array_index_type,
1326 idx++), se.expr, list);
1327 c = p;
1328 p = p->next;
1331 bound = build_int_cst (NULL_TREE, n - 1);
1332 /* Create an array type to hold them. */
1333 tmptype = build_range_type (gfc_array_index_type,
1334 gfc_index_zero_node, bound);
1335 tmptype = build_array_type (type, tmptype);
1337 init = build_constructor_from_list (tmptype, nreverse (list));
1338 TREE_CONSTANT (init) = 1;
1339 TREE_STATIC (init) = 1;
1340 /* Create a static variable to hold the data. */
1341 tmp = gfc_create_var (tmptype, "data");
1342 TREE_STATIC (tmp) = 1;
1343 TREE_CONSTANT (tmp) = 1;
1344 TREE_READONLY (tmp) = 1;
1345 DECL_INITIAL (tmp) = init;
1346 init = tmp;
1348 /* Use BUILTIN_MEMCPY to assign the values. */
1349 tmp = gfc_conv_descriptor_data_get (desc);
1350 tmp = build_fold_indirect_ref (tmp);
1351 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1352 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1353 init = gfc_build_addr_expr (NULL_TREE, init);
1355 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1356 bound = build_int_cst (NULL_TREE, n * size);
1357 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
1358 tmp, init, bound);
1359 gfc_add_expr_to_block (&body, tmp);
1361 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1362 *poffset,
1363 build_int_cst (gfc_array_index_type, n));
1365 if (!INTEGER_CST_P (*poffset))
1367 gfc_add_modify (&body, *offsetvar, *poffset);
1368 *poffset = *offsetvar;
1372 /* The frontend should already have done any expansions
1373 at compile-time. */
1374 if (!c->iterator)
1376 /* Pass the code as is. */
1377 tmp = gfc_finish_block (&body);
1378 gfc_add_expr_to_block (pblock, tmp);
1380 else
1382 /* Build the implied do-loop. */
1383 stmtblock_t implied_do_block;
1384 tree cond;
1385 tree end;
1386 tree step;
1387 tree exit_label;
1388 tree loopbody;
1389 tree tmp2;
1391 loopbody = gfc_finish_block (&body);
1393 /* Create a new block that holds the implied-do loop. A temporary
1394 loop-variable is used. */
1395 gfc_start_block(&implied_do_block);
1397 /* Initialize the loop. */
1398 gfc_init_se (&se, NULL);
1399 gfc_conv_expr_val (&se, c->iterator->start);
1400 gfc_add_block_to_block (&implied_do_block, &se.pre);
1401 gfc_add_modify (&implied_do_block, shadow_loopvar, se.expr);
1403 gfc_init_se (&se, NULL);
1404 gfc_conv_expr_val (&se, c->iterator->end);
1405 gfc_add_block_to_block (&implied_do_block, &se.pre);
1406 end = gfc_evaluate_now (se.expr, &implied_do_block);
1408 gfc_init_se (&se, NULL);
1409 gfc_conv_expr_val (&se, c->iterator->step);
1410 gfc_add_block_to_block (&implied_do_block, &se.pre);
1411 step = gfc_evaluate_now (se.expr, &implied_do_block);
1413 /* If this array expands dynamically, and the number of iterations
1414 is not constant, we won't have allocated space for the static
1415 part of C->EXPR's size. Do that now. */
1416 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1418 /* Get the number of iterations. */
1419 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1421 /* Get the static part of C->EXPR's size. */
1422 gfc_get_array_constructor_element_size (&size, c->expr);
1423 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1425 /* Grow the array by TMP * TMP2 elements. */
1426 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
1427 gfc_grow_array (&implied_do_block, desc, tmp);
1430 /* Generate the loop body. */
1431 exit_label = gfc_build_label_decl (NULL_TREE);
1432 gfc_start_block (&body);
1434 /* Generate the exit condition. Depending on the sign of
1435 the step variable we have to generate the correct
1436 comparison. */
1437 tmp = fold_build2 (GT_EXPR, boolean_type_node, step,
1438 build_int_cst (TREE_TYPE (step), 0));
1439 cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
1440 fold_build2 (GT_EXPR, boolean_type_node,
1441 shadow_loopvar, end),
1442 fold_build2 (LT_EXPR, boolean_type_node,
1443 shadow_loopvar, end));
1444 tmp = build1_v (GOTO_EXPR, exit_label);
1445 TREE_USED (exit_label) = 1;
1446 tmp = build3_v (COND_EXPR, cond, tmp,
1447 build_empty_stmt (input_location));
1448 gfc_add_expr_to_block (&body, tmp);
1450 /* The main loop body. */
1451 gfc_add_expr_to_block (&body, loopbody);
1453 /* Increase loop variable by step. */
1454 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (shadow_loopvar), shadow_loopvar, step);
1455 gfc_add_modify (&body, shadow_loopvar, tmp);
1457 /* Finish the loop. */
1458 tmp = gfc_finish_block (&body);
1459 tmp = build1_v (LOOP_EXPR, tmp);
1460 gfc_add_expr_to_block (&implied_do_block, tmp);
1462 /* Add the exit label. */
1463 tmp = build1_v (LABEL_EXPR, exit_label);
1464 gfc_add_expr_to_block (&implied_do_block, tmp);
1466 /* Finishe the implied-do loop. */
1467 tmp = gfc_finish_block(&implied_do_block);
1468 gfc_add_expr_to_block(pblock, tmp);
1470 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1473 mpz_clear (size);
1477 /* Figure out the string length of a variable reference expression.
1478 Used by get_array_ctor_strlen. */
1480 static void
1481 get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1483 gfc_ref *ref;
1484 gfc_typespec *ts;
1485 mpz_t char_len;
1487 /* Don't bother if we already know the length is a constant. */
1488 if (*len && INTEGER_CST_P (*len))
1489 return;
1491 ts = &expr->symtree->n.sym->ts;
1492 for (ref = expr->ref; ref; ref = ref->next)
1494 switch (ref->type)
1496 case REF_ARRAY:
1497 /* Array references don't change the string length. */
1498 break;
1500 case REF_COMPONENT:
1501 /* Use the length of the component. */
1502 ts = &ref->u.c.component->ts;
1503 break;
1505 case REF_SUBSTRING:
1506 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1507 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1508 break;
1509 mpz_init_set_ui (char_len, 1);
1510 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1511 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1512 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1513 *len = convert (gfc_charlen_type_node, *len);
1514 mpz_clear (char_len);
1515 return;
1517 default:
1518 /* TODO: Substrings are tricky because we can't evaluate the
1519 expression more than once. For now we just give up, and hope
1520 we can figure it out elsewhere. */
1521 return;
1525 *len = ts->cl->backend_decl;
1529 /* A catch-all to obtain the string length for anything that is not a
1530 constant, array or variable. */
1531 static void
1532 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1534 gfc_se se;
1535 gfc_ss *ss;
1537 /* Don't bother if we already know the length is a constant. */
1538 if (*len && INTEGER_CST_P (*len))
1539 return;
1541 if (!e->ref && e->ts.cl && e->ts.cl->length
1542 && e->ts.cl->length->expr_type == EXPR_CONSTANT)
1544 /* This is easy. */
1545 gfc_conv_const_charlen (e->ts.cl);
1546 *len = e->ts.cl->backend_decl;
1548 else
1550 /* Otherwise, be brutal even if inefficient. */
1551 ss = gfc_walk_expr (e);
1552 gfc_init_se (&se, NULL);
1554 /* No function call, in case of side effects. */
1555 se.no_function_call = 1;
1556 if (ss == gfc_ss_terminator)
1557 gfc_conv_expr (&se, e);
1558 else
1559 gfc_conv_expr_descriptor (&se, e, ss);
1561 /* Fix the value. */
1562 *len = gfc_evaluate_now (se.string_length, &se.pre);
1564 gfc_add_block_to_block (block, &se.pre);
1565 gfc_add_block_to_block (block, &se.post);
1567 e->ts.cl->backend_decl = *len;
1572 /* Figure out the string length of a character array constructor.
1573 If len is NULL, don't calculate the length; this happens for recursive calls
1574 when a sub-array-constructor is an element but not at the first position,
1575 so when we're not interested in the length.
1576 Returns TRUE if all elements are character constants. */
1578 bool
1579 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
1581 bool is_const;
1583 is_const = TRUE;
1585 if (c == NULL)
1587 if (len)
1588 *len = build_int_cstu (gfc_charlen_type_node, 0);
1589 return is_const;
1592 /* Loop over all constructor elements to find out is_const, but in len we
1593 want to store the length of the first, not the last, element. We can
1594 of course exit the loop as soon as is_const is found to be false. */
1595 for (; c && is_const; c = c->next)
1597 switch (c->expr->expr_type)
1599 case EXPR_CONSTANT:
1600 if (len && !(*len && INTEGER_CST_P (*len)))
1601 *len = build_int_cstu (gfc_charlen_type_node,
1602 c->expr->value.character.length);
1603 break;
1605 case EXPR_ARRAY:
1606 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1607 is_const = false;
1608 break;
1610 case EXPR_VARIABLE:
1611 is_const = false;
1612 if (len)
1613 get_array_ctor_var_strlen (c->expr, len);
1614 break;
1616 default:
1617 is_const = false;
1618 if (len)
1619 get_array_ctor_all_strlen (block, c->expr, len);
1620 break;
1623 /* After the first iteration, we don't want the length modified. */
1624 len = NULL;
1627 return is_const;
1630 /* Check whether the array constructor C consists entirely of constant
1631 elements, and if so returns the number of those elements, otherwise
1632 return zero. Note, an empty or NULL array constructor returns zero. */
1634 unsigned HOST_WIDE_INT
1635 gfc_constant_array_constructor_p (gfc_constructor * c)
1637 unsigned HOST_WIDE_INT nelem = 0;
1639 while (c)
1641 if (c->iterator
1642 || c->expr->rank > 0
1643 || c->expr->expr_type != EXPR_CONSTANT)
1644 return 0;
1645 c = c->next;
1646 nelem++;
1648 return nelem;
1652 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1653 and the tree type of it's elements, TYPE, return a static constant
1654 variable that is compile-time initialized. */
1656 tree
1657 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1659 tree tmptype, list, init, tmp;
1660 HOST_WIDE_INT nelem;
1661 gfc_constructor *c;
1662 gfc_array_spec as;
1663 gfc_se se;
1664 int i;
1666 /* First traverse the constructor list, converting the constants
1667 to tree to build an initializer. */
1668 nelem = 0;
1669 list = NULL_TREE;
1670 c = expr->value.constructor;
1671 while (c)
1673 gfc_init_se (&se, NULL);
1674 gfc_conv_constant (&se, c->expr);
1675 if (c->expr->ts.type != BT_CHARACTER)
1676 se.expr = fold_convert (type, se.expr);
1677 else if (POINTER_TYPE_P (type))
1678 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
1679 se.expr);
1680 list = tree_cons (build_int_cst (gfc_array_index_type, nelem),
1681 se.expr, list);
1682 c = c->next;
1683 nelem++;
1686 /* Next determine the tree type for the array. We use the gfortran
1687 front-end's gfc_get_nodesc_array_type in order to create a suitable
1688 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1690 memset (&as, 0, sizeof (gfc_array_spec));
1692 as.rank = expr->rank;
1693 as.type = AS_EXPLICIT;
1694 if (!expr->shape)
1696 as.lower[0] = gfc_int_expr (0);
1697 as.upper[0] = gfc_int_expr (nelem - 1);
1699 else
1700 for (i = 0; i < expr->rank; i++)
1702 int tmp = (int) mpz_get_si (expr->shape[i]);
1703 as.lower[i] = gfc_int_expr (0);
1704 as.upper[i] = gfc_int_expr (tmp - 1);
1707 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
1709 init = build_constructor_from_list (tmptype, nreverse (list));
1711 TREE_CONSTANT (init) = 1;
1712 TREE_STATIC (init) = 1;
1714 tmp = gfc_create_var (tmptype, "A");
1715 TREE_STATIC (tmp) = 1;
1716 TREE_CONSTANT (tmp) = 1;
1717 TREE_READONLY (tmp) = 1;
1718 DECL_INITIAL (tmp) = init;
1720 return tmp;
1724 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1725 This mostly initializes the scalarizer state info structure with the
1726 appropriate values to directly use the array created by the function
1727 gfc_build_constant_array_constructor. */
1729 static void
1730 gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
1731 gfc_ss * ss, tree type)
1733 gfc_ss_info *info;
1734 tree tmp;
1735 int i;
1737 tmp = gfc_build_constant_array_constructor (ss->expr, type);
1739 info = &ss->data.info;
1741 info->descriptor = tmp;
1742 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
1743 info->offset = gfc_index_zero_node;
1745 for (i = 0; i < info->dimen; i++)
1747 info->delta[i] = gfc_index_zero_node;
1748 info->start[i] = gfc_index_zero_node;
1749 info->end[i] = gfc_index_zero_node;
1750 info->stride[i] = gfc_index_one_node;
1751 info->dim[i] = i;
1754 if (info->dimen > loop->temp_dim)
1755 loop->temp_dim = info->dimen;
1758 /* Helper routine of gfc_trans_array_constructor to determine if the
1759 bounds of the loop specified by LOOP are constant and simple enough
1760 to use with gfc_trans_constant_array_constructor. Returns the
1761 iteration count of the loop if suitable, and NULL_TREE otherwise. */
1763 static tree
1764 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1766 tree size = gfc_index_one_node;
1767 tree tmp;
1768 int i;
1770 for (i = 0; i < loop->dimen; i++)
1772 /* If the bounds aren't constant, return NULL_TREE. */
1773 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1774 return NULL_TREE;
1775 if (!integer_zerop (loop->from[i]))
1777 /* Only allow nonzero "from" in one-dimensional arrays. */
1778 if (loop->dimen != 1)
1779 return NULL_TREE;
1780 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1781 loop->to[i], loop->from[i]);
1783 else
1784 tmp = loop->to[i];
1785 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1786 tmp, gfc_index_one_node);
1787 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1790 return size;
1794 /* Array constructors are handled by constructing a temporary, then using that
1795 within the scalarization loop. This is not optimal, but seems by far the
1796 simplest method. */
1798 static void
1799 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
1801 gfc_constructor *c;
1802 tree offset;
1803 tree offsetvar;
1804 tree desc;
1805 tree type;
1806 bool dynamic;
1807 bool old_first_len, old_typespec_chararray_ctor;
1808 tree old_first_len_val;
1810 /* Save the old values for nested checking. */
1811 old_first_len = first_len;
1812 old_first_len_val = first_len_val;
1813 old_typespec_chararray_ctor = typespec_chararray_ctor;
1815 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
1816 typespec was given for the array constructor. */
1817 typespec_chararray_ctor = (ss->expr->ts.cl
1818 && ss->expr->ts.cl->length_from_typespec);
1820 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1821 && ss->expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
1823 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1824 first_len = true;
1827 ss->data.info.dimen = loop->dimen;
1829 c = ss->expr->value.constructor;
1830 if (ss->expr->ts.type == BT_CHARACTER)
1832 bool const_string;
1834 /* get_array_ctor_strlen walks the elements of the constructor, if a
1835 typespec was given, we already know the string length and want the one
1836 specified there. */
1837 if (typespec_chararray_ctor && ss->expr->ts.cl->length
1838 && ss->expr->ts.cl->length->expr_type != EXPR_CONSTANT)
1840 gfc_se length_se;
1842 const_string = false;
1843 gfc_init_se (&length_se, NULL);
1844 gfc_conv_expr_type (&length_se, ss->expr->ts.cl->length,
1845 gfc_charlen_type_node);
1846 ss->string_length = length_se.expr;
1847 gfc_add_block_to_block (&loop->pre, &length_se.pre);
1848 gfc_add_block_to_block (&loop->post, &length_se.post);
1850 else
1851 const_string = get_array_ctor_strlen (&loop->pre, c,
1852 &ss->string_length);
1854 /* Complex character array constructors should have been taken care of
1855 and not end up here. */
1856 gcc_assert (ss->string_length);
1858 ss->expr->ts.cl->backend_decl = ss->string_length;
1860 type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1861 if (const_string)
1862 type = build_pointer_type (type);
1864 else
1865 type = gfc_typenode_for_spec (&ss->expr->ts);
1867 /* See if the constructor determines the loop bounds. */
1868 dynamic = false;
1870 if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
1872 /* We have a multidimensional parameter. */
1873 int n;
1874 for (n = 0; n < ss->expr->rank; n++)
1876 loop->from[n] = gfc_index_zero_node;
1877 loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
1878 gfc_index_integer_kind);
1879 loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1880 loop->to[n], gfc_index_one_node);
1884 if (loop->to[0] == NULL_TREE)
1886 mpz_t size;
1888 /* We should have a 1-dimensional, zero-based loop. */
1889 gcc_assert (loop->dimen == 1);
1890 gcc_assert (integer_zerop (loop->from[0]));
1892 /* Split the constructor size into a static part and a dynamic part.
1893 Allocate the static size up-front and record whether the dynamic
1894 size might be nonzero. */
1895 mpz_init (size);
1896 dynamic = gfc_get_array_constructor_size (&size, c);
1897 mpz_sub_ui (size, size, 1);
1898 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1899 mpz_clear (size);
1902 /* Special case constant array constructors. */
1903 if (!dynamic)
1905 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
1906 if (nelem > 0)
1908 tree size = constant_array_constructor_loop_size (loop);
1909 if (size && compare_tree_int (size, nelem) == 0)
1911 gfc_trans_constant_array_constructor (loop, ss, type);
1912 goto finish;
1917 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
1918 type, NULL_TREE, dynamic, true, false, where);
1920 desc = ss->data.info.descriptor;
1921 offset = gfc_index_zero_node;
1922 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1923 TREE_NO_WARNING (offsetvar) = 1;
1924 TREE_USED (offsetvar) = 0;
1925 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
1926 &offset, &offsetvar, dynamic);
1928 /* If the array grows dynamically, the upper bound of the loop variable
1929 is determined by the array's final upper bound. */
1930 if (dynamic)
1931 loop->to[0] = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1933 if (TREE_USED (offsetvar))
1934 pushdecl (offsetvar);
1935 else
1936 gcc_assert (INTEGER_CST_P (offset));
1937 #if 0
1938 /* Disable bound checking for now because it's probably broken. */
1939 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1941 gcc_unreachable ();
1943 #endif
1945 finish:
1946 /* Restore old values of globals. */
1947 first_len = old_first_len;
1948 first_len_val = old_first_len_val;
1949 typespec_chararray_ctor = old_typespec_chararray_ctor;
1953 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
1954 called after evaluating all of INFO's vector dimensions. Go through
1955 each such vector dimension and see if we can now fill in any missing
1956 loop bounds. */
1958 static void
1959 gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
1961 gfc_se se;
1962 tree tmp;
1963 tree desc;
1964 tree zero;
1965 int n;
1966 int dim;
1968 for (n = 0; n < loop->dimen; n++)
1970 dim = info->dim[n];
1971 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
1972 && loop->to[n] == NULL)
1974 /* Loop variable N indexes vector dimension DIM, and we don't
1975 yet know the upper bound of loop variable N. Set it to the
1976 difference between the vector's upper and lower bounds. */
1977 gcc_assert (loop->from[n] == gfc_index_zero_node);
1978 gcc_assert (info->subscript[dim]
1979 && info->subscript[dim]->type == GFC_SS_VECTOR);
1981 gfc_init_se (&se, NULL);
1982 desc = info->subscript[dim]->data.info.descriptor;
1983 zero = gfc_rank_cst[0];
1984 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1985 gfc_conv_descriptor_ubound_get (desc, zero),
1986 gfc_conv_descriptor_lbound_get (desc, zero));
1987 tmp = gfc_evaluate_now (tmp, &loop->pre);
1988 loop->to[n] = tmp;
1994 /* Add the pre and post chains for all the scalar expressions in a SS chain
1995 to loop. This is called after the loop parameters have been calculated,
1996 but before the actual scalarizing loops. */
1998 static void
1999 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2000 locus * where)
2002 gfc_se se;
2003 int n;
2005 /* TODO: This can generate bad code if there are ordering dependencies,
2006 e.g., a callee allocated function and an unknown size constructor. */
2007 gcc_assert (ss != NULL);
2009 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2011 gcc_assert (ss);
2013 switch (ss->type)
2015 case GFC_SS_SCALAR:
2016 /* Scalar expression. Evaluate this now. This includes elemental
2017 dimension indices, but not array section bounds. */
2018 gfc_init_se (&se, NULL);
2019 gfc_conv_expr (&se, ss->expr);
2020 gfc_add_block_to_block (&loop->pre, &se.pre);
2022 if (ss->expr->ts.type != BT_CHARACTER)
2024 /* Move the evaluation of scalar expressions outside the
2025 scalarization loop, except for WHERE assignments. */
2026 if (subscript)
2027 se.expr = convert(gfc_array_index_type, se.expr);
2028 if (!ss->where)
2029 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
2030 gfc_add_block_to_block (&loop->pre, &se.post);
2032 else
2033 gfc_add_block_to_block (&loop->post, &se.post);
2035 ss->data.scalar.expr = se.expr;
2036 ss->string_length = se.string_length;
2037 break;
2039 case GFC_SS_REFERENCE:
2040 /* Scalar reference. Evaluate this now. */
2041 gfc_init_se (&se, NULL);
2042 gfc_conv_expr_reference (&se, ss->expr);
2043 gfc_add_block_to_block (&loop->pre, &se.pre);
2044 gfc_add_block_to_block (&loop->post, &se.post);
2046 ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
2047 ss->string_length = se.string_length;
2048 break;
2050 case GFC_SS_SECTION:
2051 /* Add the expressions for scalar and vector subscripts. */
2052 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2053 if (ss->data.info.subscript[n])
2054 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true,
2055 where);
2057 gfc_set_vector_loop_bounds (loop, &ss->data.info);
2058 break;
2060 case GFC_SS_VECTOR:
2061 /* Get the vector's descriptor and store it in SS. */
2062 gfc_init_se (&se, NULL);
2063 gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
2064 gfc_add_block_to_block (&loop->pre, &se.pre);
2065 gfc_add_block_to_block (&loop->post, &se.post);
2066 ss->data.info.descriptor = se.expr;
2067 break;
2069 case GFC_SS_INTRINSIC:
2070 gfc_add_intrinsic_ss_code (loop, ss);
2071 break;
2073 case GFC_SS_FUNCTION:
2074 /* Array function return value. We call the function and save its
2075 result in a temporary for use inside the loop. */
2076 gfc_init_se (&se, NULL);
2077 se.loop = loop;
2078 se.ss = ss;
2079 gfc_conv_expr (&se, ss->expr);
2080 gfc_add_block_to_block (&loop->pre, &se.pre);
2081 gfc_add_block_to_block (&loop->post, &se.post);
2082 ss->string_length = se.string_length;
2083 break;
2085 case GFC_SS_CONSTRUCTOR:
2086 if (ss->expr->ts.type == BT_CHARACTER
2087 && ss->string_length == NULL
2088 && ss->expr->ts.cl
2089 && ss->expr->ts.cl->length)
2091 gfc_init_se (&se, NULL);
2092 gfc_conv_expr_type (&se, ss->expr->ts.cl->length,
2093 gfc_charlen_type_node);
2094 ss->string_length = se.expr;
2095 gfc_add_block_to_block (&loop->pre, &se.pre);
2096 gfc_add_block_to_block (&loop->post, &se.post);
2098 gfc_trans_array_constructor (loop, ss, where);
2099 break;
2101 case GFC_SS_TEMP:
2102 case GFC_SS_COMPONENT:
2103 /* Do nothing. These are handled elsewhere. */
2104 break;
2106 default:
2107 gcc_unreachable ();
2113 /* Translate expressions for the descriptor and data pointer of a SS. */
2114 /*GCC ARRAYS*/
2116 static void
2117 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2119 gfc_se se;
2120 tree tmp;
2122 /* Get the descriptor for the array to be scalarized. */
2123 gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
2124 gfc_init_se (&se, NULL);
2125 se.descriptor_only = 1;
2126 gfc_conv_expr_lhs (&se, ss->expr);
2127 gfc_add_block_to_block (block, &se.pre);
2128 ss->data.info.descriptor = se.expr;
2129 ss->string_length = se.string_length;
2131 if (base)
2133 /* Also the data pointer. */
2134 tmp = gfc_conv_array_data (se.expr);
2135 /* If this is a variable or address of a variable we use it directly.
2136 Otherwise we must evaluate it now to avoid breaking dependency
2137 analysis by pulling the expressions for elemental array indices
2138 inside the loop. */
2139 if (!(DECL_P (tmp)
2140 || (TREE_CODE (tmp) == ADDR_EXPR
2141 && DECL_P (TREE_OPERAND (tmp, 0)))))
2142 tmp = gfc_evaluate_now (tmp, block);
2143 ss->data.info.data = tmp;
2145 tmp = gfc_conv_array_offset (se.expr);
2146 ss->data.info.offset = gfc_evaluate_now (tmp, block);
2151 /* Initialize a gfc_loopinfo structure. */
2153 void
2154 gfc_init_loopinfo (gfc_loopinfo * loop)
2156 int n;
2158 memset (loop, 0, sizeof (gfc_loopinfo));
2159 gfc_init_block (&loop->pre);
2160 gfc_init_block (&loop->post);
2162 /* Initially scalarize in order. */
2163 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2164 loop->order[n] = n;
2166 loop->ss = gfc_ss_terminator;
2170 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2171 chain. */
2173 void
2174 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2176 se->loop = loop;
2180 /* Return an expression for the data pointer of an array. */
2182 tree
2183 gfc_conv_array_data (tree descriptor)
2185 tree type;
2187 type = TREE_TYPE (descriptor);
2188 if (GFC_ARRAY_TYPE_P (type))
2190 if (TREE_CODE (type) == POINTER_TYPE)
2191 return descriptor;
2192 else
2194 /* Descriptorless arrays. */
2195 return gfc_build_addr_expr (NULL_TREE, descriptor);
2198 else
2199 return gfc_conv_descriptor_data_get (descriptor);
2203 /* Return an expression for the base offset of an array. */
2205 tree
2206 gfc_conv_array_offset (tree descriptor)
2208 tree type;
2210 type = TREE_TYPE (descriptor);
2211 if (GFC_ARRAY_TYPE_P (type))
2212 return GFC_TYPE_ARRAY_OFFSET (type);
2213 else
2214 return gfc_conv_descriptor_offset_get (descriptor);
2218 /* Get an expression for the array stride. */
2220 tree
2221 gfc_conv_array_stride (tree descriptor, int dim)
2223 tree tmp;
2224 tree type;
2226 type = TREE_TYPE (descriptor);
2228 /* For descriptorless arrays use the array size. */
2229 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2230 if (tmp != NULL_TREE)
2231 return tmp;
2233 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2234 return tmp;
2238 /* Like gfc_conv_array_stride, but for the lower bound. */
2240 tree
2241 gfc_conv_array_lbound (tree descriptor, int dim)
2243 tree tmp;
2244 tree type;
2246 type = TREE_TYPE (descriptor);
2248 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2249 if (tmp != NULL_TREE)
2250 return tmp;
2252 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2253 return tmp;
2257 /* Like gfc_conv_array_stride, but for the upper bound. */
2259 tree
2260 gfc_conv_array_ubound (tree descriptor, int dim)
2262 tree tmp;
2263 tree type;
2265 type = TREE_TYPE (descriptor);
2267 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2268 if (tmp != NULL_TREE)
2269 return tmp;
2271 /* This should only ever happen when passing an assumed shape array
2272 as an actual parameter. The value will never be used. */
2273 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2274 return gfc_index_zero_node;
2276 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2277 return tmp;
2281 /* Generate code to perform an array index bound check. */
2283 static tree
2284 gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
2285 locus * where, bool check_upper)
2287 tree fault;
2288 tree tmp;
2289 char *msg;
2290 const char * name = NULL;
2292 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2293 return index;
2295 index = gfc_evaluate_now (index, &se->pre);
2297 /* We find a name for the error message. */
2298 if (se->ss)
2299 name = se->ss->expr->symtree->name;
2301 if (!name && se->loop && se->loop->ss && se->loop->ss->expr
2302 && se->loop->ss->expr->symtree)
2303 name = se->loop->ss->expr->symtree->name;
2305 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2306 && se->loop->ss->loop_chain->expr
2307 && se->loop->ss->loop_chain->expr->symtree)
2308 name = se->loop->ss->loop_chain->expr->symtree->name;
2310 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2311 && se->loop->ss->loop_chain->expr->symtree)
2312 name = se->loop->ss->loop_chain->expr->symtree->name;
2314 if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
2316 if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
2317 && se->loop->ss->expr->value.function.name)
2318 name = se->loop->ss->expr->value.function.name;
2319 else
2320 if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
2321 || se->loop->ss->type == GFC_SS_SCALAR)
2322 name = "unnamed constant";
2325 /* Check lower bound. */
2326 tmp = gfc_conv_array_lbound (descriptor, n);
2327 fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
2328 if (name)
2329 asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
2330 "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
2331 else
2332 asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
2333 gfc_msg_fault, n+1);
2334 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2335 fold_convert (long_integer_type_node, index),
2336 fold_convert (long_integer_type_node, tmp));
2337 gfc_free (msg);
2339 /* Check upper bound. */
2340 if (check_upper)
2342 tmp = gfc_conv_array_ubound (descriptor, n);
2343 fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
2344 if (name)
2345 asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
2346 " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
2347 else
2348 asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
2349 gfc_msg_fault, n+1);
2350 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2351 fold_convert (long_integer_type_node, index),
2352 fold_convert (long_integer_type_node, tmp));
2353 gfc_free (msg);
2356 return index;
2360 /* Return the offset for an index. Performs bound checking for elemental
2361 dimensions. Single element references are processed separately. */
2363 static tree
2364 gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
2365 gfc_array_ref * ar, tree stride)
2367 tree index;
2368 tree desc;
2369 tree data;
2371 /* Get the index into the array for this dimension. */
2372 if (ar)
2374 gcc_assert (ar->type != AR_ELEMENT);
2375 switch (ar->dimen_type[dim])
2377 case DIMEN_ELEMENT:
2378 /* Elemental dimension. */
2379 gcc_assert (info->subscript[dim]
2380 && info->subscript[dim]->type == GFC_SS_SCALAR);
2381 /* We've already translated this value outside the loop. */
2382 index = info->subscript[dim]->data.scalar.expr;
2384 index = gfc_trans_array_bound_check (se, info->descriptor,
2385 index, dim, &ar->where,
2386 (ar->as->type != AS_ASSUMED_SIZE
2387 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2388 break;
2390 case DIMEN_VECTOR:
2391 gcc_assert (info && se->loop);
2392 gcc_assert (info->subscript[dim]
2393 && info->subscript[dim]->type == GFC_SS_VECTOR);
2394 desc = info->subscript[dim]->data.info.descriptor;
2396 /* Get a zero-based index into the vector. */
2397 index = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2398 se->loop->loopvar[i], se->loop->from[i]);
2400 /* Multiply the index by the stride. */
2401 index = fold_build2 (MULT_EXPR, gfc_array_index_type,
2402 index, gfc_conv_array_stride (desc, 0));
2404 /* Read the vector to get an index into info->descriptor. */
2405 data = build_fold_indirect_ref (gfc_conv_array_data (desc));
2406 index = gfc_build_array_ref (data, index, NULL);
2407 index = gfc_evaluate_now (index, &se->pre);
2409 /* Do any bounds checking on the final info->descriptor index. */
2410 index = gfc_trans_array_bound_check (se, info->descriptor,
2411 index, dim, &ar->where,
2412 (ar->as->type != AS_ASSUMED_SIZE
2413 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
2414 break;
2416 case DIMEN_RANGE:
2417 /* Scalarized dimension. */
2418 gcc_assert (info && se->loop);
2420 /* Multiply the loop variable by the stride and delta. */
2421 index = se->loop->loopvar[i];
2422 if (!integer_onep (info->stride[i]))
2423 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index,
2424 info->stride[i]);
2425 if (!integer_zerop (info->delta[i]))
2426 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index,
2427 info->delta[i]);
2428 break;
2430 default:
2431 gcc_unreachable ();
2434 else
2436 /* Temporary array or derived type component. */
2437 gcc_assert (se->loop);
2438 index = se->loop->loopvar[se->loop->order[i]];
2439 if (!integer_zerop (info->delta[i]))
2440 index = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2441 index, info->delta[i]);
2444 /* Multiply by the stride. */
2445 if (!integer_onep (stride))
2446 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index, stride);
2448 return index;
2452 /* Build a scalarized reference to an array. */
2454 static void
2455 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2457 gfc_ss_info *info;
2458 tree decl = NULL_TREE;
2459 tree index;
2460 tree tmp;
2461 int n;
2463 info = &se->ss->data.info;
2464 if (ar)
2465 n = se->loop->order[0];
2466 else
2467 n = 0;
2469 index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
2470 info->stride0);
2471 /* Add the offset for this dimension to the stored offset for all other
2472 dimensions. */
2473 if (!integer_zerop (info->offset))
2474 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset);
2476 if (se->ss->expr && is_subref_array (se->ss->expr))
2477 decl = se->ss->expr->symtree->n.sym->backend_decl;
2479 tmp = build_fold_indirect_ref (info->data);
2480 se->expr = gfc_build_array_ref (tmp, index, decl);
2484 /* Translate access of temporary array. */
2486 void
2487 gfc_conv_tmp_array_ref (gfc_se * se)
2489 se->string_length = se->ss->string_length;
2490 gfc_conv_scalarized_array_ref (se, NULL);
2494 /* Build an array reference. se->expr already holds the array descriptor.
2495 This should be either a variable, indirect variable reference or component
2496 reference. For arrays which do not have a descriptor, se->expr will be
2497 the data pointer.
2498 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2500 void
2501 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2502 locus * where)
2504 int n;
2505 tree index;
2506 tree tmp;
2507 tree stride;
2508 gfc_se indexse;
2509 gfc_se tmpse;
2511 /* Handle scalarized references separately. */
2512 if (ar->type != AR_ELEMENT)
2514 gfc_conv_scalarized_array_ref (se, ar);
2515 gfc_advance_se_ss_chain (se);
2516 return;
2519 index = gfc_index_zero_node;
2521 /* Calculate the offsets from all the dimensions. */
2522 for (n = 0; n < ar->dimen; n++)
2524 /* Calculate the index for this dimension. */
2525 gfc_init_se (&indexse, se);
2526 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2527 gfc_add_block_to_block (&se->pre, &indexse.pre);
2529 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2531 /* Check array bounds. */
2532 tree cond;
2533 char *msg;
2535 /* Evaluate the indexse.expr only once. */
2536 indexse.expr = save_expr (indexse.expr);
2538 /* Lower bound. */
2539 tmp = gfc_conv_array_lbound (se->expr, n);
2540 if (sym->attr.temporary)
2542 gfc_init_se (&tmpse, se);
2543 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
2544 gfc_array_index_type);
2545 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2546 tmp = tmpse.expr;
2549 cond = fold_build2 (LT_EXPR, boolean_type_node,
2550 indexse.expr, tmp);
2551 asprintf (&msg, "%s for array '%s', "
2552 "lower bound of dimension %d exceeded (%%ld < %%ld)",
2553 gfc_msg_fault, sym->name, n+1);
2554 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2555 fold_convert (long_integer_type_node,
2556 indexse.expr),
2557 fold_convert (long_integer_type_node, tmp));
2558 gfc_free (msg);
2560 /* Upper bound, but not for the last dimension of assumed-size
2561 arrays. */
2562 if (n < ar->dimen - 1
2563 || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
2565 tmp = gfc_conv_array_ubound (se->expr, n);
2566 if (sym->attr.temporary)
2568 gfc_init_se (&tmpse, se);
2569 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
2570 gfc_array_index_type);
2571 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2572 tmp = tmpse.expr;
2575 cond = fold_build2 (GT_EXPR, boolean_type_node,
2576 indexse.expr, tmp);
2577 asprintf (&msg, "%s for array '%s', "
2578 "upper bound of dimension %d exceeded (%%ld > %%ld)",
2579 gfc_msg_fault, sym->name, n+1);
2580 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2581 fold_convert (long_integer_type_node,
2582 indexse.expr),
2583 fold_convert (long_integer_type_node, tmp));
2584 gfc_free (msg);
2588 /* Multiply the index by the stride. */
2589 stride = gfc_conv_array_stride (se->expr, n);
2590 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
2591 stride);
2593 /* And add it to the total. */
2594 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2597 tmp = gfc_conv_array_offset (se->expr);
2598 if (!integer_zerop (tmp))
2599 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
2601 /* Access the calculated element. */
2602 tmp = gfc_conv_array_data (se->expr);
2603 tmp = build_fold_indirect_ref (tmp);
2604 se->expr = gfc_build_array_ref (tmp, index, sym->backend_decl);
2608 /* Generate the code to be executed immediately before entering a
2609 scalarization loop. */
2611 static void
2612 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2613 stmtblock_t * pblock)
2615 tree index;
2616 tree stride;
2617 gfc_ss_info *info;
2618 gfc_ss *ss;
2619 gfc_se se;
2620 int i;
2622 /* This code will be executed before entering the scalarization loop
2623 for this dimension. */
2624 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2626 if ((ss->useflags & flag) == 0)
2627 continue;
2629 if (ss->type != GFC_SS_SECTION
2630 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2631 && ss->type != GFC_SS_COMPONENT)
2632 continue;
2634 info = &ss->data.info;
2636 if (dim >= info->dimen)
2637 continue;
2639 if (dim == info->dimen - 1)
2641 /* For the outermost loop calculate the offset due to any
2642 elemental dimensions. It will have been initialized with the
2643 base offset of the array. */
2644 if (info->ref)
2646 for (i = 0; i < info->ref->u.ar.dimen; i++)
2648 if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2649 continue;
2651 gfc_init_se (&se, NULL);
2652 se.loop = loop;
2653 se.expr = info->descriptor;
2654 stride = gfc_conv_array_stride (info->descriptor, i);
2655 index = gfc_conv_array_index_offset (&se, info, i, -1,
2656 &info->ref->u.ar,
2657 stride);
2658 gfc_add_block_to_block (pblock, &se.pre);
2660 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2661 info->offset, index);
2662 info->offset = gfc_evaluate_now (info->offset, pblock);
2665 i = loop->order[0];
2666 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2668 else
2669 stride = gfc_conv_array_stride (info->descriptor, 0);
2671 /* Calculate the stride of the innermost loop. Hopefully this will
2672 allow the backend optimizers to do their stuff more effectively.
2674 info->stride0 = gfc_evaluate_now (stride, pblock);
2676 else
2678 /* Add the offset for the previous loop dimension. */
2679 gfc_array_ref *ar;
2681 if (info->ref)
2683 ar = &info->ref->u.ar;
2684 i = loop->order[dim + 1];
2686 else
2688 ar = NULL;
2689 i = dim + 1;
2692 gfc_init_se (&se, NULL);
2693 se.loop = loop;
2694 se.expr = info->descriptor;
2695 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2696 index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
2697 ar, stride);
2698 gfc_add_block_to_block (pblock, &se.pre);
2699 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2700 info->offset, index);
2701 info->offset = gfc_evaluate_now (info->offset, pblock);
2704 /* Remember this offset for the second loop. */
2705 if (dim == loop->temp_dim - 1)
2706 info->saved_offset = info->offset;
2711 /* Start a scalarized expression. Creates a scope and declares loop
2712 variables. */
2714 void
2715 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2717 int dim;
2718 int n;
2719 int flags;
2721 gcc_assert (!loop->array_parameter);
2723 for (dim = loop->dimen - 1; dim >= 0; dim--)
2725 n = loop->order[dim];
2727 gfc_start_block (&loop->code[n]);
2729 /* Create the loop variable. */
2730 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2732 if (dim < loop->temp_dim)
2733 flags = 3;
2734 else
2735 flags = 1;
2736 /* Calculate values that will be constant within this loop. */
2737 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
2739 gfc_start_block (pbody);
2743 /* Generates the actual loop code for a scalarization loop. */
2745 static void
2746 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
2747 stmtblock_t * pbody)
2749 stmtblock_t block;
2750 tree cond;
2751 tree tmp;
2752 tree loopbody;
2753 tree exit_label;
2754 tree stmt;
2755 tree init;
2756 tree incr;
2758 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
2759 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
2760 && n == loop->dimen - 1)
2762 /* We create an OMP_FOR construct for the outermost scalarized loop. */
2763 init = make_tree_vec (1);
2764 cond = make_tree_vec (1);
2765 incr = make_tree_vec (1);
2767 /* Cycle statement is implemented with a goto. Exit statement must not
2768 be present for this loop. */
2769 exit_label = gfc_build_label_decl (NULL_TREE);
2770 TREE_USED (exit_label) = 1;
2772 /* Label for cycle statements (if needed). */
2773 tmp = build1_v (LABEL_EXPR, exit_label);
2774 gfc_add_expr_to_block (pbody, tmp);
2776 stmt = make_node (OMP_FOR);
2778 TREE_TYPE (stmt) = void_type_node;
2779 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
2781 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
2782 OMP_CLAUSE_SCHEDULE);
2783 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
2784 = OMP_CLAUSE_SCHEDULE_STATIC;
2785 if (ompws_flags & OMPWS_NOWAIT)
2786 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
2787 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
2789 /* Initialize the loopvar. */
2790 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
2791 loop->from[n]);
2792 OMP_FOR_INIT (stmt) = init;
2793 /* The exit condition. */
2794 TREE_VEC_ELT (cond, 0) = build2 (LE_EXPR, boolean_type_node,
2795 loop->loopvar[n], loop->to[n]);
2796 OMP_FOR_COND (stmt) = cond;
2797 /* Increment the loopvar. */
2798 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
2799 loop->loopvar[n], gfc_index_one_node);
2800 TREE_VEC_ELT (incr, 0) = fold_build2 (MODIFY_EXPR,
2801 void_type_node, loop->loopvar[n], tmp);
2802 OMP_FOR_INCR (stmt) = incr;
2804 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
2805 gfc_add_expr_to_block (&loop->code[n], stmt);
2807 else
2809 loopbody = gfc_finish_block (pbody);
2811 /* Initialize the loopvar. */
2812 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
2814 exit_label = gfc_build_label_decl (NULL_TREE);
2816 /* Generate the loop body. */
2817 gfc_init_block (&block);
2819 /* The exit condition. */
2820 cond = fold_build2 (GT_EXPR, boolean_type_node,
2821 loop->loopvar[n], loop->to[n]);
2822 tmp = build1_v (GOTO_EXPR, exit_label);
2823 TREE_USED (exit_label) = 1;
2824 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2825 gfc_add_expr_to_block (&block, tmp);
2827 /* The main body. */
2828 gfc_add_expr_to_block (&block, loopbody);
2830 /* Increment the loopvar. */
2831 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2832 loop->loopvar[n], gfc_index_one_node);
2833 gfc_add_modify (&block, loop->loopvar[n], tmp);
2835 /* Build the loop. */
2836 tmp = gfc_finish_block (&block);
2837 tmp = build1_v (LOOP_EXPR, tmp);
2838 gfc_add_expr_to_block (&loop->code[n], tmp);
2840 /* Add the exit label. */
2841 tmp = build1_v (LABEL_EXPR, exit_label);
2842 gfc_add_expr_to_block (&loop->code[n], tmp);
2848 /* Finishes and generates the loops for a scalarized expression. */
2850 void
2851 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
2853 int dim;
2854 int n;
2855 gfc_ss *ss;
2856 stmtblock_t *pblock;
2857 tree tmp;
2859 pblock = body;
2860 /* Generate the loops. */
2861 for (dim = 0; dim < loop->dimen; dim++)
2863 n = loop->order[dim];
2864 gfc_trans_scalarized_loop_end (loop, n, pblock);
2865 loop->loopvar[n] = NULL_TREE;
2866 pblock = &loop->code[n];
2869 tmp = gfc_finish_block (pblock);
2870 gfc_add_expr_to_block (&loop->pre, tmp);
2872 /* Clear all the used flags. */
2873 for (ss = loop->ss; ss; ss = ss->loop_chain)
2874 ss->useflags = 0;
2878 /* Finish the main body of a scalarized expression, and start the secondary
2879 copying body. */
2881 void
2882 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
2884 int dim;
2885 int n;
2886 stmtblock_t *pblock;
2887 gfc_ss *ss;
2889 pblock = body;
2890 /* We finish as many loops as are used by the temporary. */
2891 for (dim = 0; dim < loop->temp_dim - 1; dim++)
2893 n = loop->order[dim];
2894 gfc_trans_scalarized_loop_end (loop, n, pblock);
2895 loop->loopvar[n] = NULL_TREE;
2896 pblock = &loop->code[n];
2899 /* We don't want to finish the outermost loop entirely. */
2900 n = loop->order[loop->temp_dim - 1];
2901 gfc_trans_scalarized_loop_end (loop, n, pblock);
2903 /* Restore the initial offsets. */
2904 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2906 if ((ss->useflags & 2) == 0)
2907 continue;
2909 if (ss->type != GFC_SS_SECTION
2910 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2911 && ss->type != GFC_SS_COMPONENT)
2912 continue;
2914 ss->data.info.offset = ss->data.info.saved_offset;
2917 /* Restart all the inner loops we just finished. */
2918 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
2920 n = loop->order[dim];
2922 gfc_start_block (&loop->code[n]);
2924 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
2926 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
2929 /* Start a block for the secondary copying code. */
2930 gfc_start_block (body);
2934 /* Calculate the upper bound of an array section. */
2936 static tree
2937 gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
2939 int dim;
2940 gfc_expr *end;
2941 tree desc;
2942 tree bound;
2943 gfc_se se;
2944 gfc_ss_info *info;
2946 gcc_assert (ss->type == GFC_SS_SECTION);
2948 info = &ss->data.info;
2949 dim = info->dim[n];
2951 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2952 /* We'll calculate the upper bound once we have access to the
2953 vector's descriptor. */
2954 return NULL;
2956 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2957 desc = info->descriptor;
2958 end = info->ref->u.ar.end[dim];
2960 if (end)
2962 /* The upper bound was specified. */
2963 gfc_init_se (&se, NULL);
2964 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2965 gfc_add_block_to_block (pblock, &se.pre);
2966 bound = se.expr;
2968 else
2970 /* No upper bound was specified, so use the bound of the array. */
2971 bound = gfc_conv_array_ubound (desc, dim);
2974 return bound;
2978 /* Calculate the lower bound of an array section. */
2980 static void
2981 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
2983 gfc_expr *start;
2984 gfc_expr *end;
2985 gfc_expr *stride;
2986 tree desc;
2987 gfc_se se;
2988 gfc_ss_info *info;
2989 int dim;
2991 gcc_assert (ss->type == GFC_SS_SECTION);
2993 info = &ss->data.info;
2994 dim = info->dim[n];
2996 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2998 /* We use a zero-based index to access the vector. */
2999 info->start[n] = gfc_index_zero_node;
3000 info->end[n] = gfc_index_zero_node;
3001 info->stride[n] = gfc_index_one_node;
3002 return;
3005 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
3006 desc = info->descriptor;
3007 start = info->ref->u.ar.start[dim];
3008 end = info->ref->u.ar.end[dim];
3009 stride = info->ref->u.ar.stride[dim];
3011 /* Calculate the start of the range. For vector subscripts this will
3012 be the range of the vector. */
3013 if (start)
3015 /* Specified section start. */
3016 gfc_init_se (&se, NULL);
3017 gfc_conv_expr_type (&se, start, gfc_array_index_type);
3018 gfc_add_block_to_block (&loop->pre, &se.pre);
3019 info->start[n] = se.expr;
3021 else
3023 /* No lower bound specified so use the bound of the array. */
3024 info->start[n] = gfc_conv_array_lbound (desc, dim);
3026 info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
3028 /* Similarly calculate the end. Although this is not used in the
3029 scalarizer, it is needed when checking bounds and where the end
3030 is an expression with side-effects. */
3031 if (end)
3033 /* Specified section start. */
3034 gfc_init_se (&se, NULL);
3035 gfc_conv_expr_type (&se, end, gfc_array_index_type);
3036 gfc_add_block_to_block (&loop->pre, &se.pre);
3037 info->end[n] = se.expr;
3039 else
3041 /* No upper bound specified so use the bound of the array. */
3042 info->end[n] = gfc_conv_array_ubound (desc, dim);
3044 info->end[n] = gfc_evaluate_now (info->end[n], &loop->pre);
3046 /* Calculate the stride. */
3047 if (stride == NULL)
3048 info->stride[n] = gfc_index_one_node;
3049 else
3051 gfc_init_se (&se, NULL);
3052 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3053 gfc_add_block_to_block (&loop->pre, &se.pre);
3054 info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
3059 /* Calculates the range start and stride for a SS chain. Also gets the
3060 descriptor and data pointer. The range of vector subscripts is the size
3061 of the vector. Array bounds are also checked. */
3063 void
3064 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3066 int n;
3067 tree tmp;
3068 gfc_ss *ss;
3069 tree desc;
3071 loop->dimen = 0;
3072 /* Determine the rank of the loop. */
3073 for (ss = loop->ss;
3074 ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
3076 switch (ss->type)
3078 case GFC_SS_SECTION:
3079 case GFC_SS_CONSTRUCTOR:
3080 case GFC_SS_FUNCTION:
3081 case GFC_SS_COMPONENT:
3082 loop->dimen = ss->data.info.dimen;
3083 break;
3085 /* As usual, lbound and ubound are exceptions!. */
3086 case GFC_SS_INTRINSIC:
3087 switch (ss->expr->value.function.isym->id)
3089 case GFC_ISYM_LBOUND:
3090 case GFC_ISYM_UBOUND:
3091 loop->dimen = ss->data.info.dimen;
3093 default:
3094 break;
3097 default:
3098 break;
3102 /* We should have determined the rank of the expression by now. If
3103 not, that's bad news. */
3104 gcc_assert (loop->dimen != 0);
3106 /* Loop over all the SS in the chain. */
3107 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3109 if (ss->expr && ss->expr->shape && !ss->shape)
3110 ss->shape = ss->expr->shape;
3112 switch (ss->type)
3114 case GFC_SS_SECTION:
3115 /* Get the descriptor for the array. */
3116 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
3118 for (n = 0; n < ss->data.info.dimen; n++)
3119 gfc_conv_section_startstride (loop, ss, n);
3120 break;
3122 case GFC_SS_INTRINSIC:
3123 switch (ss->expr->value.function.isym->id)
3125 /* Fall through to supply start and stride. */
3126 case GFC_ISYM_LBOUND:
3127 case GFC_ISYM_UBOUND:
3128 break;
3129 default:
3130 continue;
3133 case GFC_SS_CONSTRUCTOR:
3134 case GFC_SS_FUNCTION:
3135 for (n = 0; n < ss->data.info.dimen; n++)
3137 ss->data.info.start[n] = gfc_index_zero_node;
3138 ss->data.info.end[n] = gfc_index_zero_node;
3139 ss->data.info.stride[n] = gfc_index_one_node;
3141 break;
3143 default:
3144 break;
3148 /* The rest is just runtime bound checking. */
3149 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3151 stmtblock_t block;
3152 tree lbound, ubound;
3153 tree end;
3154 tree size[GFC_MAX_DIMENSIONS];
3155 tree stride_pos, stride_neg, non_zerosized, tmp2;
3156 gfc_ss_info *info;
3157 char *msg;
3158 int dim;
3160 gfc_start_block (&block);
3162 for (n = 0; n < loop->dimen; n++)
3163 size[n] = NULL_TREE;
3165 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3167 stmtblock_t inner;
3169 if (ss->type != GFC_SS_SECTION)
3170 continue;
3172 gfc_start_block (&inner);
3174 /* TODO: range checking for mapped dimensions. */
3175 info = &ss->data.info;
3177 /* This code only checks ranges. Elemental and vector
3178 dimensions are checked later. */
3179 for (n = 0; n < loop->dimen; n++)
3181 bool check_upper;
3183 dim = info->dim[n];
3184 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
3185 continue;
3187 if (dim == info->ref->u.ar.dimen - 1
3188 && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
3189 || info->ref->u.ar.as->cp_was_assumed))
3190 check_upper = false;
3191 else
3192 check_upper = true;
3194 /* Zero stride is not allowed. */
3195 tmp = fold_build2 (EQ_EXPR, boolean_type_node, info->stride[n],
3196 gfc_index_zero_node);
3197 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
3198 "of array '%s'", info->dim[n]+1,
3199 ss->expr->symtree->name);
3200 gfc_trans_runtime_check (true, false, tmp, &inner,
3201 &ss->expr->where, msg);
3202 gfc_free (msg);
3204 desc = ss->data.info.descriptor;
3206 /* This is the run-time equivalent of resolve.c's
3207 check_dimension(). The logical is more readable there
3208 than it is here, with all the trees. */
3209 lbound = gfc_conv_array_lbound (desc, dim);
3210 end = info->end[n];
3211 if (check_upper)
3212 ubound = gfc_conv_array_ubound (desc, dim);
3213 else
3214 ubound = NULL;
3216 /* non_zerosized is true when the selected range is not
3217 empty. */
3218 stride_pos = fold_build2 (GT_EXPR, boolean_type_node,
3219 info->stride[n], gfc_index_zero_node);
3220 tmp = fold_build2 (LE_EXPR, boolean_type_node, info->start[n],
3221 end);
3222 stride_pos = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3223 stride_pos, tmp);
3225 stride_neg = fold_build2 (LT_EXPR, boolean_type_node,
3226 info->stride[n], gfc_index_zero_node);
3227 tmp = fold_build2 (GE_EXPR, boolean_type_node, info->start[n],
3228 end);
3229 stride_neg = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3230 stride_neg, tmp);
3231 non_zerosized = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
3232 stride_pos, stride_neg);
3234 /* Check the start of the range against the lower and upper
3235 bounds of the array, if the range is not empty. */
3236 tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
3237 lbound);
3238 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3239 non_zerosized, tmp);
3240 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
3241 " exceeded (%%ld < %%ld)", gfc_msg_fault,
3242 info->dim[n]+1, ss->expr->symtree->name);
3243 gfc_trans_runtime_check (true, false, tmp, &inner,
3244 &ss->expr->where, msg,
3245 fold_convert (long_integer_type_node,
3246 info->start[n]),
3247 fold_convert (long_integer_type_node,
3248 lbound));
3249 gfc_free (msg);
3251 if (check_upper)
3253 tmp = fold_build2 (GT_EXPR, boolean_type_node,
3254 info->start[n], ubound);
3255 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3256 non_zerosized, tmp);
3257 asprintf (&msg, "%s, upper bound of dimension %d of array "
3258 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3259 info->dim[n]+1, ss->expr->symtree->name);
3260 gfc_trans_runtime_check (true, false, tmp, &inner,
3261 &ss->expr->where, msg,
3262 fold_convert (long_integer_type_node, info->start[n]),
3263 fold_convert (long_integer_type_node, ubound));
3264 gfc_free (msg);
3267 /* Compute the last element of the range, which is not
3268 necessarily "end" (think 0:5:3, which doesn't contain 5)
3269 and check it against both lower and upper bounds. */
3270 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3271 info->start[n]);
3272 tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
3273 info->stride[n]);
3274 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3275 tmp2);
3277 tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
3278 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3279 non_zerosized, tmp);
3280 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
3281 " exceeded (%%ld < %%ld)", gfc_msg_fault,
3282 info->dim[n]+1, ss->expr->symtree->name);
3283 gfc_trans_runtime_check (true, false, tmp, &inner,
3284 &ss->expr->where, msg,
3285 fold_convert (long_integer_type_node,
3286 tmp2),
3287 fold_convert (long_integer_type_node,
3288 lbound));
3289 gfc_free (msg);
3291 if (check_upper)
3293 tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
3294 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3295 non_zerosized, tmp);
3296 asprintf (&msg, "%s, upper bound of dimension %d of array "
3297 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3298 info->dim[n]+1, ss->expr->symtree->name);
3299 gfc_trans_runtime_check (true, false, tmp, &inner,
3300 &ss->expr->where, msg,
3301 fold_convert (long_integer_type_node, tmp2),
3302 fold_convert (long_integer_type_node, ubound));
3303 gfc_free (msg);
3306 /* Check the section sizes match. */
3307 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3308 info->start[n]);
3309 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
3310 info->stride[n]);
3311 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3312 gfc_index_one_node, tmp);
3313 tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
3314 build_int_cst (gfc_array_index_type, 0));
3315 /* We remember the size of the first section, and check all the
3316 others against this. */
3317 if (size[n])
3319 tree tmp3;
3321 tmp3 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
3322 asprintf (&msg, "%s, size mismatch for dimension %d "
3323 "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
3324 info->dim[n]+1, ss->expr->symtree->name);
3325 gfc_trans_runtime_check (true, false, tmp3, &inner,
3326 &ss->expr->where, msg,
3327 fold_convert (long_integer_type_node, tmp),
3328 fold_convert (long_integer_type_node, size[n]));
3329 gfc_free (msg);
3331 else
3332 size[n] = gfc_evaluate_now (tmp, &inner);
3335 tmp = gfc_finish_block (&inner);
3337 /* For optional arguments, only check bounds if the argument is
3338 present. */
3339 if (ss->expr->symtree->n.sym->attr.optional
3340 || ss->expr->symtree->n.sym->attr.not_always_present)
3341 tmp = build3_v (COND_EXPR,
3342 gfc_conv_expr_present (ss->expr->symtree->n.sym),
3343 tmp, build_empty_stmt (input_location));
3345 gfc_add_expr_to_block (&block, tmp);
3349 tmp = gfc_finish_block (&block);
3350 gfc_add_expr_to_block (&loop->pre, tmp);
3355 /* Return true if the two SS could be aliased, i.e. both point to the same data
3356 object. */
3357 /* TODO: resolve aliases based on frontend expressions. */
3359 static int
3360 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
3362 gfc_ref *lref;
3363 gfc_ref *rref;
3364 gfc_symbol *lsym;
3365 gfc_symbol *rsym;
3367 lsym = lss->expr->symtree->n.sym;
3368 rsym = rss->expr->symtree->n.sym;
3369 if (gfc_symbols_could_alias (lsym, rsym))
3370 return 1;
3372 if (rsym->ts.type != BT_DERIVED
3373 && lsym->ts.type != BT_DERIVED)
3374 return 0;
3376 /* For derived types we must check all the component types. We can ignore
3377 array references as these will have the same base type as the previous
3378 component ref. */
3379 for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
3381 if (lref->type != REF_COMPONENT)
3382 continue;
3384 if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
3385 return 1;
3387 for (rref = rss->expr->ref; rref != rss->data.info.ref;
3388 rref = rref->next)
3390 if (rref->type != REF_COMPONENT)
3391 continue;
3393 if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
3394 return 1;
3398 for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
3400 if (rref->type != REF_COMPONENT)
3401 break;
3403 if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
3404 return 1;
3407 return 0;
3411 /* Resolve array data dependencies. Creates a temporary if required. */
3412 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
3413 dependency.c. */
3415 void
3416 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
3417 gfc_ss * rss)
3419 gfc_ss *ss;
3420 gfc_ref *lref;
3421 gfc_ref *rref;
3422 gfc_ref *aref;
3423 int nDepend = 0;
3424 int temp_dim = 0;
3426 loop->temp_ss = NULL;
3427 aref = dest->data.info.ref;
3428 temp_dim = 0;
3430 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
3432 if (ss->type != GFC_SS_SECTION)
3433 continue;
3435 if (dest->expr->symtree->n.sym != ss->expr->symtree->n.sym)
3437 if (gfc_could_be_alias (dest, ss)
3438 || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3440 nDepend = 1;
3441 break;
3444 else
3446 lref = dest->expr->ref;
3447 rref = ss->expr->ref;
3449 nDepend = gfc_dep_resolver (lref, rref);
3450 if (nDepend == 1)
3451 break;
3452 #if 0
3453 /* TODO : loop shifting. */
3454 if (nDepend == 1)
3456 /* Mark the dimensions for LOOP SHIFTING */
3457 for (n = 0; n < loop->dimen; n++)
3459 int dim = dest->data.info.dim[n];
3461 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3462 depends[n] = 2;
3463 else if (! gfc_is_same_range (&lref->u.ar,
3464 &rref->u.ar, dim, 0))
3465 depends[n] = 1;
3468 /* Put all the dimensions with dependencies in the
3469 innermost loops. */
3470 dim = 0;
3471 for (n = 0; n < loop->dimen; n++)
3473 gcc_assert (loop->order[n] == n);
3474 if (depends[n])
3475 loop->order[dim++] = n;
3477 temp_dim = dim;
3478 for (n = 0; n < loop->dimen; n++)
3480 if (! depends[n])
3481 loop->order[dim++] = n;
3484 gcc_assert (dim == loop->dimen);
3485 break;
3487 #endif
3491 if (nDepend == 1)
3493 tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
3494 if (GFC_ARRAY_TYPE_P (base_type)
3495 || GFC_DESCRIPTOR_TYPE_P (base_type))
3496 base_type = gfc_get_element_type (base_type);
3497 loop->temp_ss = gfc_get_ss ();
3498 loop->temp_ss->type = GFC_SS_TEMP;
3499 loop->temp_ss->data.temp.type = base_type;
3500 loop->temp_ss->string_length = dest->string_length;
3501 loop->temp_ss->data.temp.dimen = loop->dimen;
3502 loop->temp_ss->next = gfc_ss_terminator;
3503 gfc_add_ss_to_loop (loop, loop->temp_ss);
3505 else
3506 loop->temp_ss = NULL;
3510 /* Initialize the scalarization loop. Creates the loop variables. Determines
3511 the range of the loop variables. Creates a temporary if required.
3512 Calculates how to transform from loop variables to array indices for each
3513 expression. Also generates code for scalar expressions which have been
3514 moved outside the loop. */
3516 void
3517 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
3519 int n;
3520 int dim;
3521 gfc_ss_info *info;
3522 gfc_ss_info *specinfo;
3523 gfc_ss *ss;
3524 tree tmp;
3525 tree len;
3526 gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
3527 bool dynamic[GFC_MAX_DIMENSIONS];
3528 gfc_constructor *c;
3529 mpz_t *cshape;
3530 mpz_t i;
3532 mpz_init (i);
3533 for (n = 0; n < loop->dimen; n++)
3535 loopspec[n] = NULL;
3536 dynamic[n] = false;
3537 /* We use one SS term, and use that to determine the bounds of the
3538 loop for this dimension. We try to pick the simplest term. */
3539 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3541 if (ss->shape)
3543 /* The frontend has worked out the size for us. */
3544 if (!loopspec[n] || !loopspec[n]->shape
3545 || !integer_zerop (loopspec[n]->data.info.start[n]))
3546 /* Prefer zero-based descriptors if possible. */
3547 loopspec[n] = ss;
3548 continue;
3551 if (ss->type == GFC_SS_CONSTRUCTOR)
3553 /* An unknown size constructor will always be rank one.
3554 Higher rank constructors will either have known shape,
3555 or still be wrapped in a call to reshape. */
3556 gcc_assert (loop->dimen == 1);
3558 /* Always prefer to use the constructor bounds if the size
3559 can be determined at compile time. Prefer not to otherwise,
3560 since the general case involves realloc, and it's better to
3561 avoid that overhead if possible. */
3562 c = ss->expr->value.constructor;
3563 dynamic[n] = gfc_get_array_constructor_size (&i, c);
3564 if (!dynamic[n] || !loopspec[n])
3565 loopspec[n] = ss;
3566 continue;
3569 /* TODO: Pick the best bound if we have a choice between a
3570 function and something else. */
3571 if (ss->type == GFC_SS_FUNCTION)
3573 loopspec[n] = ss;
3574 continue;
3577 if (ss->type != GFC_SS_SECTION)
3578 continue;
3580 if (loopspec[n])
3581 specinfo = &loopspec[n]->data.info;
3582 else
3583 specinfo = NULL;
3584 info = &ss->data.info;
3586 if (!specinfo)
3587 loopspec[n] = ss;
3588 /* Criteria for choosing a loop specifier (most important first):
3589 doesn't need realloc
3590 stride of one
3591 known stride
3592 known lower bound
3593 known upper bound
3595 else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
3596 loopspec[n] = ss;
3597 else if (integer_onep (info->stride[n])
3598 && !integer_onep (specinfo->stride[n]))
3599 loopspec[n] = ss;
3600 else if (INTEGER_CST_P (info->stride[n])
3601 && !INTEGER_CST_P (specinfo->stride[n]))
3602 loopspec[n] = ss;
3603 else if (INTEGER_CST_P (info->start[n])
3604 && !INTEGER_CST_P (specinfo->start[n]))
3605 loopspec[n] = ss;
3606 /* We don't work out the upper bound.
3607 else if (INTEGER_CST_P (info->finish[n])
3608 && ! INTEGER_CST_P (specinfo->finish[n]))
3609 loopspec[n] = ss; */
3612 /* We should have found the scalarization loop specifier. If not,
3613 that's bad news. */
3614 gcc_assert (loopspec[n]);
3616 info = &loopspec[n]->data.info;
3618 /* Set the extents of this range. */
3619 cshape = loopspec[n]->shape;
3620 if (cshape && INTEGER_CST_P (info->start[n])
3621 && INTEGER_CST_P (info->stride[n]))
3623 loop->from[n] = info->start[n];
3624 mpz_set (i, cshape[n]);
3625 mpz_sub_ui (i, i, 1);
3626 /* To = from + (size - 1) * stride. */
3627 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
3628 if (!integer_onep (info->stride[n]))
3629 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3630 tmp, info->stride[n]);
3631 loop->to[n] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3632 loop->from[n], tmp);
3634 else
3636 loop->from[n] = info->start[n];
3637 switch (loopspec[n]->type)
3639 case GFC_SS_CONSTRUCTOR:
3640 /* The upper bound is calculated when we expand the
3641 constructor. */
3642 gcc_assert (loop->to[n] == NULL_TREE);
3643 break;
3645 case GFC_SS_SECTION:
3646 /* Use the end expression if it exists and is not constant,
3647 so that it is only evaluated once. */
3648 if (info->end[n] && !INTEGER_CST_P (info->end[n]))
3649 loop->to[n] = info->end[n];
3650 else
3651 loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
3652 &loop->pre);
3653 break;
3655 case GFC_SS_FUNCTION:
3656 /* The loop bound will be set when we generate the call. */
3657 gcc_assert (loop->to[n] == NULL_TREE);
3658 break;
3660 default:
3661 gcc_unreachable ();
3665 /* Transform everything so we have a simple incrementing variable. */
3666 if (integer_onep (info->stride[n]))
3667 info->delta[n] = gfc_index_zero_node;
3668 else
3670 /* Set the delta for this section. */
3671 info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
3672 /* Number of iterations is (end - start + step) / step.
3673 with start = 0, this simplifies to
3674 last = end / step;
3675 for (i = 0; i<=last; i++){...}; */
3676 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3677 loop->to[n], loop->from[n]);
3678 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type,
3679 tmp, info->stride[n]);
3680 tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
3681 build_int_cst (gfc_array_index_type, -1));
3682 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
3683 /* Make the loop variable start at 0. */
3684 loop->from[n] = gfc_index_zero_node;
3688 /* Add all the scalar code that can be taken out of the loops.
3689 This may include calculating the loop bounds, so do it before
3690 allocating the temporary. */
3691 gfc_add_loop_ss_code (loop, loop->ss, false, where);
3693 /* If we want a temporary then create it. */
3694 if (loop->temp_ss != NULL)
3696 gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
3698 /* Make absolutely sure that this is a complete type. */
3699 if (loop->temp_ss->string_length)
3700 loop->temp_ss->data.temp.type
3701 = gfc_get_character_type_len_for_eltype
3702 (TREE_TYPE (loop->temp_ss->data.temp.type),
3703 loop->temp_ss->string_length);
3705 tmp = loop->temp_ss->data.temp.type;
3706 len = loop->temp_ss->string_length;
3707 n = loop->temp_ss->data.temp.dimen;
3708 memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
3709 loop->temp_ss->type = GFC_SS_SECTION;
3710 loop->temp_ss->data.info.dimen = n;
3711 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
3712 &loop->temp_ss->data.info, tmp, NULL_TREE,
3713 false, true, false, where);
3716 for (n = 0; n < loop->temp_dim; n++)
3717 loopspec[loop->order[n]] = NULL;
3719 mpz_clear (i);
3721 /* For array parameters we don't have loop variables, so don't calculate the
3722 translations. */
3723 if (loop->array_parameter)
3724 return;
3726 /* Calculate the translation from loop variables to array indices. */
3727 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3729 if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT
3730 && ss->type != GFC_SS_CONSTRUCTOR)
3732 continue;
3734 info = &ss->data.info;
3736 for (n = 0; n < info->dimen; n++)
3738 dim = info->dim[n];
3740 /* If we are specifying the range the delta is already set. */
3741 if (loopspec[n] != ss)
3743 /* Calculate the offset relative to the loop variable.
3744 First multiply by the stride. */
3745 tmp = loop->from[n];
3746 if (!integer_onep (info->stride[n]))
3747 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3748 tmp, info->stride[n]);
3750 /* Then subtract this from our starting value. */
3751 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3752 info->start[n], tmp);
3754 info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
3761 /* Fills in an array descriptor, and returns the size of the array. The size
3762 will be a simple_val, ie a variable or a constant. Also calculates the
3763 offset of the base. Returns the size of the array.
3765 stride = 1;
3766 offset = 0;
3767 for (n = 0; n < rank; n++)
3769 a.lbound[n] = specified_lower_bound;
3770 offset = offset + a.lbond[n] * stride;
3771 size = 1 - lbound;
3772 a.ubound[n] = specified_upper_bound;
3773 a.stride[n] = stride;
3774 size = siz >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
3775 stride = stride * size;
3777 return (stride);
3778 } */
3779 /*GCC ARRAYS*/
3781 static tree
3782 gfc_array_init_size (tree descriptor, int rank, tree * poffset,
3783 gfc_expr ** lower, gfc_expr ** upper,
3784 stmtblock_t * pblock)
3786 tree type;
3787 tree tmp;
3788 tree size;
3789 tree offset;
3790 tree stride;
3791 tree cond;
3792 tree or_expr;
3793 tree thencase;
3794 tree elsecase;
3795 tree var;
3796 stmtblock_t thenblock;
3797 stmtblock_t elseblock;
3798 gfc_expr *ubound;
3799 gfc_se se;
3800 int n;
3802 type = TREE_TYPE (descriptor);
3804 stride = gfc_index_one_node;
3805 offset = gfc_index_zero_node;
3807 /* Set the dtype. */
3808 tmp = gfc_conv_descriptor_dtype (descriptor);
3809 gfc_add_modify (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
3811 or_expr = NULL_TREE;
3813 for (n = 0; n < rank; n++)
3815 /* We have 3 possibilities for determining the size of the array:
3816 lower == NULL => lbound = 1, ubound = upper[n]
3817 upper[n] = NULL => lbound = 1, ubound = lower[n]
3818 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
3819 ubound = upper[n];
3821 /* Set lower bound. */
3822 gfc_init_se (&se, NULL);
3823 if (lower == NULL)
3824 se.expr = gfc_index_one_node;
3825 else
3827 gcc_assert (lower[n]);
3828 if (ubound)
3830 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
3831 gfc_add_block_to_block (pblock, &se.pre);
3833 else
3835 se.expr = gfc_index_one_node;
3836 ubound = lower[n];
3839 gfc_conv_descriptor_lbound_set (pblock, descriptor, gfc_rank_cst[n],
3840 se.expr);
3842 /* Work out the offset for this component. */
3843 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
3844 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
3846 /* Start the calculation for the size of this dimension. */
3847 size = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3848 gfc_index_one_node, se.expr);
3850 /* Set upper bound. */
3851 gfc_init_se (&se, NULL);
3852 gcc_assert (ubound);
3853 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
3854 gfc_add_block_to_block (pblock, &se.pre);
3856 gfc_conv_descriptor_ubound_set (pblock, descriptor, gfc_rank_cst[n], se.expr);
3858 /* Store the stride. */
3859 gfc_conv_descriptor_stride_set (pblock, descriptor, gfc_rank_cst[n], stride);
3861 /* Calculate the size of this dimension. */
3862 size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
3864 /* Check whether the size for this dimension is negative. */
3865 cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3866 gfc_index_zero_node);
3867 if (n == 0)
3868 or_expr = cond;
3869 else
3870 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
3872 size = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
3873 gfc_index_zero_node, size);
3875 /* Multiply the stride by the number of elements in this dimension. */
3876 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, size);
3877 stride = gfc_evaluate_now (stride, pblock);
3880 /* The stride is the number of elements in the array, so multiply by the
3881 size of an element to get the total size. */
3882 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3883 size = fold_build2 (MULT_EXPR, gfc_array_index_type, stride,
3884 fold_convert (gfc_array_index_type, tmp));
3886 if (poffset != NULL)
3888 offset = gfc_evaluate_now (offset, pblock);
3889 *poffset = offset;
3892 if (integer_zerop (or_expr))
3893 return size;
3894 if (integer_onep (or_expr))
3895 return gfc_index_zero_node;
3897 var = gfc_create_var (TREE_TYPE (size), "size");
3898 gfc_start_block (&thenblock);
3899 gfc_add_modify (&thenblock, var, gfc_index_zero_node);
3900 thencase = gfc_finish_block (&thenblock);
3902 gfc_start_block (&elseblock);
3903 gfc_add_modify (&elseblock, var, size);
3904 elsecase = gfc_finish_block (&elseblock);
3906 tmp = gfc_evaluate_now (or_expr, pblock);
3907 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
3908 gfc_add_expr_to_block (pblock, tmp);
3910 return var;
3914 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
3915 the work for an ALLOCATE statement. */
3916 /*GCC ARRAYS*/
3918 bool
3919 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
3921 tree tmp;
3922 tree pointer;
3923 tree offset;
3924 tree size;
3925 gfc_expr **lower;
3926 gfc_expr **upper;
3927 gfc_ref *ref, *prev_ref = NULL;
3928 bool allocatable_array;
3930 ref = expr->ref;
3932 /* Find the last reference in the chain. */
3933 while (ref && ref->next != NULL)
3935 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
3936 prev_ref = ref;
3937 ref = ref->next;
3940 if (ref == NULL || ref->type != REF_ARRAY)
3941 return false;
3943 if (!prev_ref)
3944 allocatable_array = expr->symtree->n.sym->attr.allocatable;
3945 else
3946 allocatable_array = prev_ref->u.c.component->attr.allocatable;
3948 /* Figure out the size of the array. */
3949 switch (ref->u.ar.type)
3951 case AR_ELEMENT:
3952 lower = NULL;
3953 upper = ref->u.ar.start;
3954 break;
3956 case AR_FULL:
3957 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
3959 lower = ref->u.ar.as->lower;
3960 upper = ref->u.ar.as->upper;
3961 break;
3963 case AR_SECTION:
3964 lower = ref->u.ar.start;
3965 upper = ref->u.ar.end;
3966 break;
3968 default:
3969 gcc_unreachable ();
3970 break;
3973 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
3974 lower, upper, &se->pre);
3976 /* Allocate memory to store the data. */
3977 pointer = gfc_conv_descriptor_data_get (se->expr);
3978 STRIP_NOPS (pointer);
3980 /* The allocate_array variants take the old pointer as first argument. */
3981 if (allocatable_array)
3982 tmp = gfc_allocate_array_with_status (&se->pre, pointer, size, pstat, expr);
3983 else
3984 tmp = gfc_allocate_with_status (&se->pre, size, pstat);
3985 tmp = fold_build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
3986 gfc_add_expr_to_block (&se->pre, tmp);
3988 gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
3990 if (expr->ts.type == BT_DERIVED
3991 && expr->ts.derived->attr.alloc_comp)
3993 tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
3994 ref->u.ar.as->rank);
3995 gfc_add_expr_to_block (&se->pre, tmp);
3998 return true;
4002 /* Deallocate an array variable. Also used when an allocated variable goes
4003 out of scope. */
4004 /*GCC ARRAYS*/
4006 tree
4007 gfc_array_deallocate (tree descriptor, tree pstat, gfc_expr* expr)
4009 tree var;
4010 tree tmp;
4011 stmtblock_t block;
4013 gfc_start_block (&block);
4014 /* Get a pointer to the data. */
4015 var = gfc_conv_descriptor_data_get (descriptor);
4016 STRIP_NOPS (var);
4018 /* Parameter is the address of the data component. */
4019 tmp = gfc_deallocate_with_status (var, pstat, false, expr);
4020 gfc_add_expr_to_block (&block, tmp);
4022 /* Zero the data pointer. */
4023 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
4024 var, build_int_cst (TREE_TYPE (var), 0));
4025 gfc_add_expr_to_block (&block, tmp);
4027 return gfc_finish_block (&block);
4031 /* Create an array constructor from an initialization expression.
4032 We assume the frontend already did any expansions and conversions. */
4034 tree
4035 gfc_conv_array_initializer (tree type, gfc_expr * expr)
4037 gfc_constructor *c;
4038 tree tmp;
4039 mpz_t maxval;
4040 gfc_se se;
4041 HOST_WIDE_INT hi;
4042 unsigned HOST_WIDE_INT lo;
4043 tree index, range;
4044 VEC(constructor_elt,gc) *v = NULL;
4046 switch (expr->expr_type)
4048 case EXPR_CONSTANT:
4049 case EXPR_STRUCTURE:
4050 /* A single scalar or derived type value. Create an array with all
4051 elements equal to that value. */
4052 gfc_init_se (&se, NULL);
4054 if (expr->expr_type == EXPR_CONSTANT)
4055 gfc_conv_constant (&se, expr);
4056 else
4057 gfc_conv_structure (&se, expr, 1);
4059 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4060 gcc_assert (tmp && INTEGER_CST_P (tmp));
4061 hi = TREE_INT_CST_HIGH (tmp);
4062 lo = TREE_INT_CST_LOW (tmp);
4063 lo++;
4064 if (lo == 0)
4065 hi++;
4066 /* This will probably eat buckets of memory for large arrays. */
4067 while (hi != 0 || lo != 0)
4069 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
4070 if (lo == 0)
4071 hi--;
4072 lo--;
4074 break;
4076 case EXPR_ARRAY:
4077 /* Create a vector of all the elements. */
4078 for (c = expr->value.constructor; c; c = c->next)
4080 if (c->iterator)
4082 /* Problems occur when we get something like
4083 integer :: a(lots) = (/(i, i=1, lots)/) */
4084 gfc_error_now ("The number of elements in the array constructor "
4085 "at %L requires an increase of the allowed %d "
4086 "upper limit. See -fmax-array-constructor "
4087 "option", &expr->where,
4088 gfc_option.flag_max_array_constructor);
4089 return NULL_TREE;
4091 if (mpz_cmp_si (c->n.offset, 0) != 0)
4092 index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
4093 else
4094 index = NULL_TREE;
4095 mpz_init (maxval);
4096 if (mpz_cmp_si (c->repeat, 0) != 0)
4098 tree tmp1, tmp2;
4100 mpz_set (maxval, c->repeat);
4101 mpz_add (maxval, c->n.offset, maxval);
4102 mpz_sub_ui (maxval, maxval, 1);
4103 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
4104 if (mpz_cmp_si (c->n.offset, 0) != 0)
4106 mpz_add_ui (maxval, c->n.offset, 1);
4107 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
4109 else
4110 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
4112 range = fold_build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
4114 else
4115 range = NULL;
4116 mpz_clear (maxval);
4118 gfc_init_se (&se, NULL);
4119 switch (c->expr->expr_type)
4121 case EXPR_CONSTANT:
4122 gfc_conv_constant (&se, c->expr);
4123 if (range == NULL_TREE)
4124 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4125 else
4127 if (index != NULL_TREE)
4128 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4129 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
4131 break;
4133 case EXPR_STRUCTURE:
4134 gfc_conv_structure (&se, c->expr, 1);
4135 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4136 break;
4139 default:
4140 /* Catch those occasional beasts that do not simplify
4141 for one reason or another, assuming that if they are
4142 standard defying the frontend will catch them. */
4143 gfc_conv_expr (&se, c->expr);
4144 if (range == NULL_TREE)
4145 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4146 else
4148 if (index != NULL_TREE)
4149 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4150 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
4152 break;
4155 break;
4157 case EXPR_NULL:
4158 return gfc_build_null_descriptor (type);
4160 default:
4161 gcc_unreachable ();
4164 /* Create a constructor from the list of elements. */
4165 tmp = build_constructor (type, v);
4166 TREE_CONSTANT (tmp) = 1;
4167 return tmp;
4171 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
4172 returns the size (in elements) of the array. */
4174 static tree
4175 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
4176 stmtblock_t * pblock)
4178 gfc_array_spec *as;
4179 tree size;
4180 tree stride;
4181 tree offset;
4182 tree ubound;
4183 tree lbound;
4184 tree tmp;
4185 gfc_se se;
4187 int dim;
4189 as = sym->as;
4191 size = gfc_index_one_node;
4192 offset = gfc_index_zero_node;
4193 for (dim = 0; dim < as->rank; dim++)
4195 /* Evaluate non-constant array bound expressions. */
4196 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
4197 if (as->lower[dim] && !INTEGER_CST_P (lbound))
4199 gfc_init_se (&se, NULL);
4200 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
4201 gfc_add_block_to_block (pblock, &se.pre);
4202 gfc_add_modify (pblock, lbound, se.expr);
4204 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
4205 if (as->upper[dim] && !INTEGER_CST_P (ubound))
4207 gfc_init_se (&se, NULL);
4208 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
4209 gfc_add_block_to_block (pblock, &se.pre);
4210 gfc_add_modify (pblock, ubound, se.expr);
4212 /* The offset of this dimension. offset = offset - lbound * stride. */
4213 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, size);
4214 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
4216 /* The size of this dimension, and the stride of the next. */
4217 if (dim + 1 < as->rank)
4218 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
4219 else
4220 stride = GFC_TYPE_ARRAY_SIZE (type);
4222 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
4224 /* Calculate stride = size * (ubound + 1 - lbound). */
4225 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4226 gfc_index_one_node, lbound);
4227 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp);
4228 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
4229 if (stride)
4230 gfc_add_modify (pblock, stride, tmp);
4231 else
4232 stride = gfc_evaluate_now (tmp, pblock);
4234 /* Make sure that negative size arrays are translated
4235 to being zero size. */
4236 tmp = fold_build2 (GE_EXPR, boolean_type_node,
4237 stride, gfc_index_zero_node);
4238 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, tmp,
4239 stride, gfc_index_zero_node);
4240 gfc_add_modify (pblock, stride, tmp);
4243 size = stride;
4246 gfc_trans_vla_type_sizes (sym, pblock);
4248 *poffset = offset;
4249 return size;
4253 /* Generate code to initialize/allocate an array variable. */
4255 tree
4256 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
4258 stmtblock_t block;
4259 tree type;
4260 tree tmp;
4261 tree size;
4262 tree offset;
4263 bool onstack;
4265 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
4267 /* Do nothing for USEd variables. */
4268 if (sym->attr.use_assoc)
4269 return fnbody;
4271 type = TREE_TYPE (decl);
4272 gcc_assert (GFC_ARRAY_TYPE_P (type));
4273 onstack = TREE_CODE (type) != POINTER_TYPE;
4275 gfc_start_block (&block);
4277 /* Evaluate character string length. */
4278 if (sym->ts.type == BT_CHARACTER
4279 && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4281 gfc_conv_string_length (sym->ts.cl, NULL, &block);
4283 gfc_trans_vla_type_sizes (sym, &block);
4285 /* Emit a DECL_EXPR for this variable, which will cause the
4286 gimplifier to allocate storage, and all that good stuff. */
4287 tmp = fold_build1 (DECL_EXPR, TREE_TYPE (decl), decl);
4288 gfc_add_expr_to_block (&block, tmp);
4291 if (onstack)
4293 gfc_add_expr_to_block (&block, fnbody);
4294 return gfc_finish_block (&block);
4297 type = TREE_TYPE (type);
4299 gcc_assert (!sym->attr.use_assoc);
4300 gcc_assert (!TREE_STATIC (decl));
4301 gcc_assert (!sym->module);
4303 if (sym->ts.type == BT_CHARACTER
4304 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4305 gfc_conv_string_length (sym->ts.cl, NULL, &block);
4307 size = gfc_trans_array_bounds (type, sym, &offset, &block);
4309 /* Don't actually allocate space for Cray Pointees. */
4310 if (sym->attr.cray_pointee)
4312 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4313 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4314 gfc_add_expr_to_block (&block, fnbody);
4315 return gfc_finish_block (&block);
4318 /* The size is the number of elements in the array, so multiply by the
4319 size of an element to get the total size. */
4320 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4321 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
4322 fold_convert (gfc_array_index_type, tmp));
4324 /* Allocate memory to hold the data. */
4325 tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
4326 gfc_add_modify (&block, decl, tmp);
4328 /* Set offset of the array. */
4329 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4330 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4333 /* Automatic arrays should not have initializers. */
4334 gcc_assert (!sym->value);
4336 gfc_add_expr_to_block (&block, fnbody);
4338 /* Free the temporary. */
4339 tmp = gfc_call_free (convert (pvoid_type_node, decl));
4340 gfc_add_expr_to_block (&block, tmp);
4342 return gfc_finish_block (&block);
4346 /* Generate entry and exit code for g77 calling convention arrays. */
4348 tree
4349 gfc_trans_g77_array (gfc_symbol * sym, tree body)
4351 tree parm;
4352 tree type;
4353 locus loc;
4354 tree offset;
4355 tree tmp;
4356 tree stmt;
4357 stmtblock_t block;
4359 gfc_get_backend_locus (&loc);
4360 gfc_set_backend_locus (&sym->declared_at);
4362 /* Descriptor type. */
4363 parm = sym->backend_decl;
4364 type = TREE_TYPE (parm);
4365 gcc_assert (GFC_ARRAY_TYPE_P (type));
4367 gfc_start_block (&block);
4369 if (sym->ts.type == BT_CHARACTER
4370 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4371 gfc_conv_string_length (sym->ts.cl, NULL, &block);
4373 /* Evaluate the bounds of the array. */
4374 gfc_trans_array_bounds (type, sym, &offset, &block);
4376 /* Set the offset. */
4377 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4378 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4380 /* Set the pointer itself if we aren't using the parameter directly. */
4381 if (TREE_CODE (parm) != PARM_DECL)
4383 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
4384 gfc_add_modify (&block, parm, tmp);
4386 stmt = gfc_finish_block (&block);
4388 gfc_set_backend_locus (&loc);
4390 gfc_start_block (&block);
4392 /* Add the initialization code to the start of the function. */
4394 if (sym->attr.optional || sym->attr.not_always_present)
4396 tmp = gfc_conv_expr_present (sym);
4397 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
4400 gfc_add_expr_to_block (&block, stmt);
4401 gfc_add_expr_to_block (&block, body);
4403 return gfc_finish_block (&block);
4407 /* Modify the descriptor of an array parameter so that it has the
4408 correct lower bound. Also move the upper bound accordingly.
4409 If the array is not packed, it will be copied into a temporary.
4410 For each dimension we set the new lower and upper bounds. Then we copy the
4411 stride and calculate the offset for this dimension. We also work out
4412 what the stride of a packed array would be, and see it the two match.
4413 If the array need repacking, we set the stride to the values we just
4414 calculated, recalculate the offset and copy the array data.
4415 Code is also added to copy the data back at the end of the function.
4418 tree
4419 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
4421 tree size;
4422 tree type;
4423 tree offset;
4424 locus loc;
4425 stmtblock_t block;
4426 stmtblock_t cleanup;
4427 tree lbound;
4428 tree ubound;
4429 tree dubound;
4430 tree dlbound;
4431 tree dumdesc;
4432 tree tmp;
4433 tree stmt;
4434 tree stride, stride2;
4435 tree stmt_packed;
4436 tree stmt_unpacked;
4437 tree partial;
4438 gfc_se se;
4439 int n;
4440 int checkparm;
4441 int no_repack;
4442 bool optional_arg;
4444 /* Do nothing for pointer and allocatable arrays. */
4445 if (sym->attr.pointer || sym->attr.allocatable)
4446 return body;
4448 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
4449 return gfc_trans_g77_array (sym, body);
4451 gfc_get_backend_locus (&loc);
4452 gfc_set_backend_locus (&sym->declared_at);
4454 /* Descriptor type. */
4455 type = TREE_TYPE (tmpdesc);
4456 gcc_assert (GFC_ARRAY_TYPE_P (type));
4457 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4458 dumdesc = build_fold_indirect_ref (dumdesc);
4459 gfc_start_block (&block);
4461 if (sym->ts.type == BT_CHARACTER
4462 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4463 gfc_conv_string_length (sym->ts.cl, NULL, &block);
4465 checkparm = (sym->as->type == AS_EXPLICIT
4466 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
4468 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
4469 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
4471 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
4473 /* For non-constant shape arrays we only check if the first dimension
4474 is contiguous. Repacking higher dimensions wouldn't gain us
4475 anything as we still don't know the array stride. */
4476 partial = gfc_create_var (boolean_type_node, "partial");
4477 TREE_USED (partial) = 1;
4478 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
4479 tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
4480 gfc_add_modify (&block, partial, tmp);
4482 else
4484 partial = NULL_TREE;
4487 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
4488 here, however I think it does the right thing. */
4489 if (no_repack)
4491 /* Set the first stride. */
4492 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
4493 stride = gfc_evaluate_now (stride, &block);
4495 tmp = fold_build2 (EQ_EXPR, boolean_type_node,
4496 stride, gfc_index_zero_node);
4497 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, tmp,
4498 gfc_index_one_node, stride);
4499 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
4500 gfc_add_modify (&block, stride, tmp);
4502 /* Allow the user to disable array repacking. */
4503 stmt_unpacked = NULL_TREE;
4505 else
4507 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
4508 /* A library call to repack the array if necessary. */
4509 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4510 stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
4512 stride = gfc_index_one_node;
4514 if (gfc_option.warn_array_temp)
4515 gfc_warning ("Creating array temporary at %L", &loc);
4518 /* This is for the case where the array data is used directly without
4519 calling the repack function. */
4520 if (no_repack || partial != NULL_TREE)
4521 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
4522 else
4523 stmt_packed = NULL_TREE;
4525 /* Assign the data pointer. */
4526 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4528 /* Don't repack unknown shape arrays when the first stride is 1. */
4529 tmp = fold_build3 (COND_EXPR, TREE_TYPE (stmt_packed),
4530 partial, stmt_packed, stmt_unpacked);
4532 else
4533 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
4534 gfc_add_modify (&block, tmpdesc, fold_convert (type, tmp));
4536 offset = gfc_index_zero_node;
4537 size = gfc_index_one_node;
4539 /* Evaluate the bounds of the array. */
4540 for (n = 0; n < sym->as->rank; n++)
4542 if (checkparm || !sym->as->upper[n])
4544 /* Get the bounds of the actual parameter. */
4545 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
4546 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
4548 else
4550 dubound = NULL_TREE;
4551 dlbound = NULL_TREE;
4554 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
4555 if (!INTEGER_CST_P (lbound))
4557 gfc_init_se (&se, NULL);
4558 gfc_conv_expr_type (&se, sym->as->lower[n],
4559 gfc_array_index_type);
4560 gfc_add_block_to_block (&block, &se.pre);
4561 gfc_add_modify (&block, lbound, se.expr);
4564 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
4565 /* Set the desired upper bound. */
4566 if (sym->as->upper[n])
4568 /* We know what we want the upper bound to be. */
4569 if (!INTEGER_CST_P (ubound))
4571 gfc_init_se (&se, NULL);
4572 gfc_conv_expr_type (&se, sym->as->upper[n],
4573 gfc_array_index_type);
4574 gfc_add_block_to_block (&block, &se.pre);
4575 gfc_add_modify (&block, ubound, se.expr);
4578 /* Check the sizes match. */
4579 if (checkparm)
4581 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
4582 char * msg;
4584 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4585 ubound, lbound);
4586 stride2 = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4587 dubound, dlbound);
4588 tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
4589 asprintf (&msg, "%s for dimension %d of array '%s'",
4590 gfc_msg_bounds, n+1, sym->name);
4591 gfc_trans_runtime_check (true, false, tmp, &block, &loc, msg);
4592 gfc_free (msg);
4595 else
4597 /* For assumed shape arrays move the upper bound by the same amount
4598 as the lower bound. */
4599 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4600 dubound, dlbound);
4601 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound);
4602 gfc_add_modify (&block, ubound, tmp);
4604 /* The offset of this dimension. offset = offset - lbound * stride. */
4605 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, stride);
4606 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
4608 /* The size of this dimension, and the stride of the next. */
4609 if (n + 1 < sym->as->rank)
4611 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
4613 if (no_repack || partial != NULL_TREE)
4615 stmt_unpacked =
4616 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
4619 /* Figure out the stride if not a known constant. */
4620 if (!INTEGER_CST_P (stride))
4622 if (no_repack)
4623 stmt_packed = NULL_TREE;
4624 else
4626 /* Calculate stride = size * (ubound + 1 - lbound). */
4627 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4628 gfc_index_one_node, lbound);
4629 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4630 ubound, tmp);
4631 size = fold_build2 (MULT_EXPR, gfc_array_index_type,
4632 size, tmp);
4633 stmt_packed = size;
4636 /* Assign the stride. */
4637 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4638 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, partial,
4639 stmt_unpacked, stmt_packed);
4640 else
4641 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
4642 gfc_add_modify (&block, stride, tmp);
4645 else
4647 stride = GFC_TYPE_ARRAY_SIZE (type);
4649 if (stride && !INTEGER_CST_P (stride))
4651 /* Calculate size = stride * (ubound + 1 - lbound). */
4652 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4653 gfc_index_one_node, lbound);
4654 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4655 ubound, tmp);
4656 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4657 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
4658 gfc_add_modify (&block, stride, tmp);
4663 /* Set the offset. */
4664 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4665 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
4667 gfc_trans_vla_type_sizes (sym, &block);
4669 stmt = gfc_finish_block (&block);
4671 gfc_start_block (&block);
4673 /* Only do the entry/initialization code if the arg is present. */
4674 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4675 optional_arg = (sym->attr.optional
4676 || (sym->ns->proc_name->attr.entry_master
4677 && sym->attr.dummy));
4678 if (optional_arg)
4680 tmp = gfc_conv_expr_present (sym);
4681 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
4683 gfc_add_expr_to_block (&block, stmt);
4685 /* Add the main function body. */
4686 gfc_add_expr_to_block (&block, body);
4688 /* Cleanup code. */
4689 if (!no_repack)
4691 gfc_start_block (&cleanup);
4693 if (sym->attr.intent != INTENT_IN)
4695 /* Copy the data back. */
4696 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
4697 gfc_add_expr_to_block (&cleanup, tmp);
4700 /* Free the temporary. */
4701 tmp = gfc_call_free (tmpdesc);
4702 gfc_add_expr_to_block (&cleanup, tmp);
4704 stmt = gfc_finish_block (&cleanup);
4706 /* Only do the cleanup if the array was repacked. */
4707 tmp = build_fold_indirect_ref (dumdesc);
4708 tmp = gfc_conv_descriptor_data_get (tmp);
4709 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
4710 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
4712 if (optional_arg)
4714 tmp = gfc_conv_expr_present (sym);
4715 stmt = build3_v (COND_EXPR, tmp, stmt,
4716 build_empty_stmt (input_location));
4718 gfc_add_expr_to_block (&block, stmt);
4720 /* We don't need to free any memory allocated by internal_pack as it will
4721 be freed at the end of the function by pop_context. */
4722 return gfc_finish_block (&block);
4726 /* Calculate the overall offset, including subreferences. */
4727 static void
4728 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
4729 bool subref, gfc_expr *expr)
4731 tree tmp;
4732 tree field;
4733 tree stride;
4734 tree index;
4735 gfc_ref *ref;
4736 gfc_se start;
4737 int n;
4739 /* If offset is NULL and this is not a subreferenced array, there is
4740 nothing to do. */
4741 if (offset == NULL_TREE)
4743 if (subref)
4744 offset = gfc_index_zero_node;
4745 else
4746 return;
4749 tmp = gfc_conv_array_data (desc);
4750 tmp = build_fold_indirect_ref (tmp);
4751 tmp = gfc_build_array_ref (tmp, offset, NULL);
4753 /* Offset the data pointer for pointer assignments from arrays with
4754 subreferences; e.g. my_integer => my_type(:)%integer_component. */
4755 if (subref)
4757 /* Go past the array reference. */
4758 for (ref = expr->ref; ref; ref = ref->next)
4759 if (ref->type == REF_ARRAY &&
4760 ref->u.ar.type != AR_ELEMENT)
4762 ref = ref->next;
4763 break;
4766 /* Calculate the offset for each subsequent subreference. */
4767 for (; ref; ref = ref->next)
4769 switch (ref->type)
4771 case REF_COMPONENT:
4772 field = ref->u.c.component->backend_decl;
4773 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
4774 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
4775 tmp, field, NULL_TREE);
4776 break;
4778 case REF_SUBSTRING:
4779 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
4780 gfc_init_se (&start, NULL);
4781 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
4782 gfc_add_block_to_block (block, &start.pre);
4783 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
4784 break;
4786 case REF_ARRAY:
4787 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
4788 && ref->u.ar.type == AR_ELEMENT);
4790 /* TODO - Add bounds checking. */
4791 stride = gfc_index_one_node;
4792 index = gfc_index_zero_node;
4793 for (n = 0; n < ref->u.ar.dimen; n++)
4795 tree itmp;
4796 tree jtmp;
4798 /* Update the index. */
4799 gfc_init_se (&start, NULL);
4800 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
4801 itmp = gfc_evaluate_now (start.expr, block);
4802 gfc_init_se (&start, NULL);
4803 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
4804 jtmp = gfc_evaluate_now (start.expr, block);
4805 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, itmp, jtmp);
4806 itmp = fold_build2 (MULT_EXPR, gfc_array_index_type, itmp, stride);
4807 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, itmp, index);
4808 index = gfc_evaluate_now (index, block);
4810 /* Update the stride. */
4811 gfc_init_se (&start, NULL);
4812 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
4813 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, start.expr, jtmp);
4814 itmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4815 gfc_index_one_node, itmp);
4816 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, itmp);
4817 stride = gfc_evaluate_now (stride, block);
4820 /* Apply the index to obtain the array element. */
4821 tmp = gfc_build_array_ref (tmp, index, NULL);
4822 break;
4824 default:
4825 gcc_unreachable ();
4826 break;
4831 /* Set the target data pointer. */
4832 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
4833 gfc_conv_descriptor_data_set (block, parm, offset);
4837 /* gfc_conv_expr_descriptor needs the string length an expression
4838 so that the size of the temporary can be obtained. This is done
4839 by adding up the string lengths of all the elements in the
4840 expression. Function with non-constant expressions have their
4841 string lengths mapped onto the actual arguments using the
4842 interface mapping machinery in trans-expr.c. */
4843 static void
4844 get_array_charlen (gfc_expr *expr, gfc_se *se)
4846 gfc_interface_mapping mapping;
4847 gfc_formal_arglist *formal;
4848 gfc_actual_arglist *arg;
4849 gfc_se tse;
4851 if (expr->ts.cl->length
4852 && gfc_is_constant_expr (expr->ts.cl->length))
4854 if (!expr->ts.cl->backend_decl)
4855 gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
4856 return;
4859 switch (expr->expr_type)
4861 case EXPR_OP:
4862 get_array_charlen (expr->value.op.op1, se);
4864 /* For parentheses the expression ts.cl is identical. */
4865 if (expr->value.op.op == INTRINSIC_PARENTHESES)
4866 return;
4868 expr->ts.cl->backend_decl =
4869 gfc_create_var (gfc_charlen_type_node, "sln");
4871 if (expr->value.op.op2)
4873 get_array_charlen (expr->value.op.op2, se);
4875 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
4877 /* Add the string lengths and assign them to the expression
4878 string length backend declaration. */
4879 gfc_add_modify (&se->pre, expr->ts.cl->backend_decl,
4880 fold_build2 (PLUS_EXPR, gfc_charlen_type_node,
4881 expr->value.op.op1->ts.cl->backend_decl,
4882 expr->value.op.op2->ts.cl->backend_decl));
4884 else
4885 gfc_add_modify (&se->pre, expr->ts.cl->backend_decl,
4886 expr->value.op.op1->ts.cl->backend_decl);
4887 break;
4889 case EXPR_FUNCTION:
4890 if (expr->value.function.esym == NULL
4891 || expr->ts.cl->length->expr_type == EXPR_CONSTANT)
4893 gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
4894 break;
4897 /* Map expressions involving the dummy arguments onto the actual
4898 argument expressions. */
4899 gfc_init_interface_mapping (&mapping);
4900 formal = expr->symtree->n.sym->formal;
4901 arg = expr->value.function.actual;
4903 /* Set se = NULL in the calls to the interface mapping, to suppress any
4904 backend stuff. */
4905 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
4907 if (!arg->expr)
4908 continue;
4909 if (formal->sym)
4910 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
4913 gfc_init_se (&tse, NULL);
4915 /* Build the expression for the character length and convert it. */
4916 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.cl->length);
4918 gfc_add_block_to_block (&se->pre, &tse.pre);
4919 gfc_add_block_to_block (&se->post, &tse.post);
4920 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
4921 tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
4922 build_int_cst (gfc_charlen_type_node, 0));
4923 expr->ts.cl->backend_decl = tse.expr;
4924 gfc_free_interface_mapping (&mapping);
4925 break;
4927 default:
4928 gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
4929 break;
4935 /* Convert an array for passing as an actual argument. Expressions and
4936 vector subscripts are evaluated and stored in a temporary, which is then
4937 passed. For whole arrays the descriptor is passed. For array sections
4938 a modified copy of the descriptor is passed, but using the original data.
4940 This function is also used for array pointer assignments, and there
4941 are three cases:
4943 - se->want_pointer && !se->direct_byref
4944 EXPR is an actual argument. On exit, se->expr contains a
4945 pointer to the array descriptor.
4947 - !se->want_pointer && !se->direct_byref
4948 EXPR is an actual argument to an intrinsic function or the
4949 left-hand side of a pointer assignment. On exit, se->expr
4950 contains the descriptor for EXPR.
4952 - !se->want_pointer && se->direct_byref
4953 EXPR is the right-hand side of a pointer assignment and
4954 se->expr is the descriptor for the previously-evaluated
4955 left-hand side. The function creates an assignment from
4956 EXPR to se->expr. */
4958 void
4959 gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
4961 gfc_loopinfo loop;
4962 gfc_ss *secss;
4963 gfc_ss_info *info;
4964 int need_tmp;
4965 int n;
4966 tree tmp;
4967 tree desc;
4968 stmtblock_t block;
4969 tree start;
4970 tree offset;
4971 int full;
4972 bool subref_array_target = false;
4974 gcc_assert (ss != gfc_ss_terminator);
4976 /* Special case things we know we can pass easily. */
4977 switch (expr->expr_type)
4979 case EXPR_VARIABLE:
4980 /* If we have a linear array section, we can pass it directly.
4981 Otherwise we need to copy it into a temporary. */
4983 /* Find the SS for the array section. */
4984 secss = ss;
4985 while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
4986 secss = secss->next;
4988 gcc_assert (secss != gfc_ss_terminator);
4989 info = &secss->data.info;
4991 /* Get the descriptor for the array. */
4992 gfc_conv_ss_descriptor (&se->pre, secss, 0);
4993 desc = info->descriptor;
4995 subref_array_target = se->direct_byref && is_subref_array (expr);
4996 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
4997 && !subref_array_target;
4999 if (need_tmp)
5000 full = 0;
5001 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5003 /* Create a new descriptor if the array doesn't have one. */
5004 full = 0;
5006 else if (info->ref->u.ar.type == AR_FULL)
5007 full = 1;
5008 else if (se->direct_byref)
5009 full = 0;
5010 else
5011 full = gfc_full_array_ref_p (info->ref);
5013 if (full)
5015 if (se->direct_byref)
5017 /* Copy the descriptor for pointer assignments. */
5018 gfc_add_modify (&se->pre, se->expr, desc);
5020 /* Add any offsets from subreferences. */
5021 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
5022 subref_array_target, expr);
5024 else if (se->want_pointer)
5026 /* We pass full arrays directly. This means that pointers and
5027 allocatable arrays should also work. */
5028 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
5030 else
5032 se->expr = desc;
5035 if (expr->ts.type == BT_CHARACTER)
5036 se->string_length = gfc_get_expr_charlen (expr);
5038 return;
5040 break;
5042 case EXPR_FUNCTION:
5043 /* A transformational function return value will be a temporary
5044 array descriptor. We still need to go through the scalarizer
5045 to create the descriptor. Elemental functions ar handled as
5046 arbitrary expressions, i.e. copy to a temporary. */
5047 secss = ss;
5048 /* Look for the SS for this function. */
5049 while (secss != gfc_ss_terminator
5050 && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
5051 secss = secss->next;
5053 if (se->direct_byref)
5055 gcc_assert (secss != gfc_ss_terminator);
5057 /* For pointer assignments pass the descriptor directly. */
5058 se->ss = secss;
5059 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
5060 gfc_conv_expr (se, expr);
5061 return;
5064 if (secss == gfc_ss_terminator)
5066 /* Elemental function. */
5067 need_tmp = 1;
5068 if (expr->ts.type == BT_CHARACTER
5069 && expr->ts.cl->length->expr_type != EXPR_CONSTANT)
5070 get_array_charlen (expr, se);
5072 info = NULL;
5074 else
5076 /* Transformational function. */
5077 info = &secss->data.info;
5078 need_tmp = 0;
5080 break;
5082 case EXPR_ARRAY:
5083 /* Constant array constructors don't need a temporary. */
5084 if (ss->type == GFC_SS_CONSTRUCTOR
5085 && expr->ts.type != BT_CHARACTER
5086 && gfc_constant_array_constructor_p (expr->value.constructor))
5088 need_tmp = 0;
5089 info = &ss->data.info;
5090 secss = ss;
5092 else
5094 need_tmp = 1;
5095 secss = NULL;
5096 info = NULL;
5098 break;
5100 default:
5101 /* Something complicated. Copy it into a temporary. */
5102 need_tmp = 1;
5103 secss = NULL;
5104 info = NULL;
5105 break;
5108 gfc_init_loopinfo (&loop);
5110 /* Associate the SS with the loop. */
5111 gfc_add_ss_to_loop (&loop, ss);
5113 /* Tell the scalarizer not to bother creating loop variables, etc. */
5114 if (!need_tmp)
5115 loop.array_parameter = 1;
5116 else
5117 /* The right-hand side of a pointer assignment mustn't use a temporary. */
5118 gcc_assert (!se->direct_byref);
5120 /* Setup the scalarizing loops and bounds. */
5121 gfc_conv_ss_startstride (&loop);
5123 if (need_tmp)
5125 /* Tell the scalarizer to make a temporary. */
5126 loop.temp_ss = gfc_get_ss ();
5127 loop.temp_ss->type = GFC_SS_TEMP;
5128 loop.temp_ss->next = gfc_ss_terminator;
5130 if (expr->ts.type == BT_CHARACTER
5131 && !expr->ts.cl->backend_decl)
5132 get_array_charlen (expr, se);
5134 loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
5136 if (expr->ts.type == BT_CHARACTER)
5137 loop.temp_ss->string_length = expr->ts.cl->backend_decl;
5138 else
5139 loop.temp_ss->string_length = NULL;
5141 se->string_length = loop.temp_ss->string_length;
5142 loop.temp_ss->data.temp.dimen = loop.dimen;
5143 gfc_add_ss_to_loop (&loop, loop.temp_ss);
5146 gfc_conv_loop_setup (&loop, & expr->where);
5148 if (need_tmp)
5150 /* Copy into a temporary and pass that. We don't need to copy the data
5151 back because expressions and vector subscripts must be INTENT_IN. */
5152 /* TODO: Optimize passing function return values. */
5153 gfc_se lse;
5154 gfc_se rse;
5156 /* Start the copying loops. */
5157 gfc_mark_ss_chain_used (loop.temp_ss, 1);
5158 gfc_mark_ss_chain_used (ss, 1);
5159 gfc_start_scalarized_body (&loop, &block);
5161 /* Copy each data element. */
5162 gfc_init_se (&lse, NULL);
5163 gfc_copy_loopinfo_to_se (&lse, &loop);
5164 gfc_init_se (&rse, NULL);
5165 gfc_copy_loopinfo_to_se (&rse, &loop);
5167 lse.ss = loop.temp_ss;
5168 rse.ss = ss;
5170 gfc_conv_scalarized_array_ref (&lse, NULL);
5171 if (expr->ts.type == BT_CHARACTER)
5173 gfc_conv_expr (&rse, expr);
5174 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
5175 rse.expr = build_fold_indirect_ref (rse.expr);
5177 else
5178 gfc_conv_expr_val (&rse, expr);
5180 gfc_add_block_to_block (&block, &rse.pre);
5181 gfc_add_block_to_block (&block, &lse.pre);
5183 lse.string_length = rse.string_length;
5184 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
5185 expr->expr_type == EXPR_VARIABLE);
5186 gfc_add_expr_to_block (&block, tmp);
5188 /* Finish the copying loops. */
5189 gfc_trans_scalarizing_loops (&loop, &block);
5191 desc = loop.temp_ss->data.info.descriptor;
5193 gcc_assert (is_gimple_lvalue (desc));
5195 else if (expr->expr_type == EXPR_FUNCTION)
5197 desc = info->descriptor;
5198 se->string_length = ss->string_length;
5200 else
5202 /* We pass sections without copying to a temporary. Make a new
5203 descriptor and point it at the section we want. The loop variable
5204 limits will be the limits of the section.
5205 A function may decide to repack the array to speed up access, but
5206 we're not bothered about that here. */
5207 int dim, ndim;
5208 tree parm;
5209 tree parmtype;
5210 tree stride;
5211 tree from;
5212 tree to;
5213 tree base;
5215 /* Set the string_length for a character array. */
5216 if (expr->ts.type == BT_CHARACTER)
5217 se->string_length = gfc_get_expr_charlen (expr);
5219 desc = info->descriptor;
5220 gcc_assert (secss && secss != gfc_ss_terminator);
5221 if (se->direct_byref)
5223 /* For pointer assignments we fill in the destination. */
5224 parm = se->expr;
5225 parmtype = TREE_TYPE (parm);
5227 else
5229 /* Otherwise make a new one. */
5230 parmtype = gfc_get_element_type (TREE_TYPE (desc));
5231 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
5232 loop.from, loop.to, 0,
5233 GFC_ARRAY_UNKNOWN);
5234 parm = gfc_create_var (parmtype, "parm");
5237 offset = gfc_index_zero_node;
5238 dim = 0;
5240 /* The following can be somewhat confusing. We have two
5241 descriptors, a new one and the original array.
5242 {parm, parmtype, dim} refer to the new one.
5243 {desc, type, n, secss, loop} refer to the original, which maybe
5244 a descriptorless array.
5245 The bounds of the scalarization are the bounds of the section.
5246 We don't have to worry about numeric overflows when calculating
5247 the offsets because all elements are within the array data. */
5249 /* Set the dtype. */
5250 tmp = gfc_conv_descriptor_dtype (parm);
5251 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
5253 /* Set offset for assignments to pointer only to zero if it is not
5254 the full array. */
5255 if (se->direct_byref
5256 && info->ref && info->ref->u.ar.type != AR_FULL)
5257 base = gfc_index_zero_node;
5258 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5259 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
5260 else
5261 base = NULL_TREE;
5263 ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
5264 for (n = 0; n < ndim; n++)
5266 stride = gfc_conv_array_stride (desc, n);
5268 /* Work out the offset. */
5269 if (info->ref
5270 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
5272 gcc_assert (info->subscript[n]
5273 && info->subscript[n]->type == GFC_SS_SCALAR);
5274 start = info->subscript[n]->data.scalar.expr;
5276 else
5278 /* Check we haven't somehow got out of sync. */
5279 gcc_assert (info->dim[dim] == n);
5281 /* Evaluate and remember the start of the section. */
5282 start = info->start[dim];
5283 stride = gfc_evaluate_now (stride, &loop.pre);
5286 tmp = gfc_conv_array_lbound (desc, n);
5287 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp);
5289 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
5290 offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
5292 if (info->ref
5293 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
5295 /* For elemental dimensions, we only need the offset. */
5296 continue;
5299 /* Vector subscripts need copying and are handled elsewhere. */
5300 if (info->ref)
5301 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
5303 /* Set the new lower bound. */
5304 from = loop.from[dim];
5305 to = loop.to[dim];
5307 /* If we have an array section or are assigning make sure that
5308 the lower bound is 1. References to the full
5309 array should otherwise keep the original bounds. */
5310 if ((!info->ref
5311 || info->ref->u.ar.type != AR_FULL)
5312 && !integer_onep (from))
5314 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
5315 gfc_index_one_node, from);
5316 to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
5317 from = gfc_index_one_node;
5319 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
5320 gfc_rank_cst[dim], from);
5322 /* Set the new upper bound. */
5323 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
5324 gfc_rank_cst[dim], to);
5326 /* Multiply the stride by the section stride to get the
5327 total stride. */
5328 stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
5329 stride, info->stride[dim]);
5331 if (se->direct_byref
5332 && info->ref
5333 && info->ref->u.ar.type != AR_FULL)
5335 base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
5336 base, stride);
5338 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5340 tmp = gfc_conv_array_lbound (desc, n);
5341 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
5342 tmp, loop.from[dim]);
5343 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base),
5344 tmp, gfc_conv_array_stride (desc, n));
5345 base = fold_build2 (PLUS_EXPR, TREE_TYPE (base),
5346 tmp, base);
5349 /* Store the new stride. */
5350 gfc_conv_descriptor_stride_set (&loop.pre, parm,
5351 gfc_rank_cst[dim], stride);
5353 dim++;
5356 if (se->data_not_needed)
5357 gfc_conv_descriptor_data_set (&loop.pre, parm,
5358 gfc_index_zero_node);
5359 else
5360 /* Point the data pointer at the 1st element in the section. */
5361 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
5362 subref_array_target, expr);
5364 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5365 && !se->data_not_needed)
5367 /* Set the offset. */
5368 gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
5370 else
5372 /* Only the callee knows what the correct offset it, so just set
5373 it to zero here. */
5374 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
5376 desc = parm;
5379 if (!se->direct_byref)
5381 /* Get a pointer to the new descriptor. */
5382 if (se->want_pointer)
5383 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
5384 else
5385 se->expr = desc;
5388 gfc_add_block_to_block (&se->pre, &loop.pre);
5389 gfc_add_block_to_block (&se->post, &loop.post);
5391 /* Cleanup the scalarizer. */
5392 gfc_cleanup_loop (&loop);
5395 /* Helper function for gfc_conv_array_parameter if array size needs to be
5396 computed. */
5398 static void
5399 array_parameter_size (tree desc, gfc_expr *expr, tree *size)
5401 tree elem;
5402 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5403 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
5404 else if (expr->rank > 1)
5405 *size = build_call_expr (gfor_fndecl_size0, 1,
5406 gfc_build_addr_expr (NULL, desc));
5407 else
5409 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
5410 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
5412 *size = fold_build2 (MINUS_EXPR, gfc_array_index_type, ubound, lbound);
5413 *size = fold_build2 (PLUS_EXPR, gfc_array_index_type, *size,
5414 gfc_index_one_node);
5415 *size = fold_build2 (MAX_EXPR, gfc_array_index_type, *size,
5416 gfc_index_zero_node);
5418 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
5419 *size = fold_build2 (MULT_EXPR, gfc_array_index_type, *size,
5420 fold_convert (gfc_array_index_type, elem));
5423 /* Convert an array for passing as an actual parameter. */
5424 /* TODO: Optimize passing g77 arrays. */
5426 void
5427 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
5428 const gfc_symbol *fsym, const char *proc_name,
5429 tree *size)
5431 tree ptr;
5432 tree desc;
5433 tree tmp = NULL_TREE;
5434 tree stmt;
5435 tree parent = DECL_CONTEXT (current_function_decl);
5436 bool full_array_var, this_array_result;
5437 gfc_symbol *sym;
5438 stmtblock_t block;
5440 full_array_var = (expr->expr_type == EXPR_VARIABLE
5441 && expr->ref->type == REF_ARRAY
5442 && expr->ref->u.ar.type == AR_FULL);
5443 sym = full_array_var ? expr->symtree->n.sym : NULL;
5445 /* The symbol should have an array specification. */
5446 gcc_assert (!sym || sym->as);
5448 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
5450 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
5451 expr->ts.cl->backend_decl = tmp;
5452 se->string_length = tmp;
5455 /* Is this the result of the enclosing procedure? */
5456 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
5457 if (this_array_result
5458 && (sym->backend_decl != current_function_decl)
5459 && (sym->backend_decl != parent))
5460 this_array_result = false;
5462 /* Passing address of the array if it is not pointer or assumed-shape. */
5463 if (full_array_var && g77 && !this_array_result)
5465 tmp = gfc_get_symbol_decl (sym);
5467 if (sym->ts.type == BT_CHARACTER)
5468 se->string_length = sym->ts.cl->backend_decl;
5469 if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE
5470 && !sym->attr.allocatable)
5472 /* Some variables are declared directly, others are declared as
5473 pointers and allocated on the heap. */
5474 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
5475 se->expr = tmp;
5476 else
5477 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
5478 if (size)
5479 array_parameter_size (tmp, expr, size);
5480 return;
5482 if (sym->attr.allocatable)
5484 if (sym->attr.dummy || sym->attr.result)
5486 gfc_conv_expr_descriptor (se, expr, ss);
5487 tmp = se->expr;
5489 if (size)
5490 array_parameter_size (tmp, expr, size);
5491 se->expr = gfc_conv_array_data (tmp);
5492 return;
5496 if (this_array_result)
5498 /* Result of the enclosing function. */
5499 gfc_conv_expr_descriptor (se, expr, ss);
5500 if (size)
5501 array_parameter_size (se->expr, expr, size);
5502 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
5504 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
5505 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
5506 se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
5508 return;
5510 else
5512 /* Every other type of array. */
5513 se->want_pointer = 1;
5514 gfc_conv_expr_descriptor (se, expr, ss);
5515 if (size)
5516 array_parameter_size (build_fold_indirect_ref (se->expr),
5517 expr, size);
5520 /* Deallocate the allocatable components of structures that are
5521 not variable. */
5522 if (expr->ts.type == BT_DERIVED
5523 && expr->ts.derived->attr.alloc_comp
5524 && expr->expr_type != EXPR_VARIABLE)
5526 tmp = build_fold_indirect_ref (se->expr);
5527 tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
5528 gfc_add_expr_to_block (&se->post, tmp);
5531 if (g77)
5533 desc = se->expr;
5534 /* Repack the array. */
5536 if (gfc_option.warn_array_temp)
5538 if (fsym)
5539 gfc_warning ("Creating array temporary at %L for argument '%s'",
5540 &expr->where, fsym->name);
5541 else
5542 gfc_warning ("Creating array temporary at %L", &expr->where);
5545 ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
5547 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
5549 tmp = gfc_conv_expr_present (sym);
5550 ptr = build3 (COND_EXPR, TREE_TYPE (se->expr), tmp,
5551 fold_convert (TREE_TYPE (se->expr), ptr),
5552 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
5555 ptr = gfc_evaluate_now (ptr, &se->pre);
5557 se->expr = ptr;
5559 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
5561 char * msg;
5563 if (fsym && proc_name)
5564 asprintf (&msg, "An array temporary was created for argument "
5565 "'%s' of procedure '%s'", fsym->name, proc_name);
5566 else
5567 asprintf (&msg, "An array temporary was created");
5569 tmp = build_fold_indirect_ref (desc);
5570 tmp = gfc_conv_array_data (tmp);
5571 tmp = fold_build2 (NE_EXPR, boolean_type_node,
5572 fold_convert (TREE_TYPE (tmp), ptr), tmp);
5574 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
5575 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
5576 gfc_conv_expr_present (sym), tmp);
5578 gfc_trans_runtime_check (false, true, tmp, &se->pre,
5579 &expr->where, msg);
5580 gfc_free (msg);
5583 gfc_start_block (&block);
5585 /* Copy the data back. */
5586 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
5588 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
5589 gfc_add_expr_to_block (&block, tmp);
5592 /* Free the temporary. */
5593 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
5594 gfc_add_expr_to_block (&block, tmp);
5596 stmt = gfc_finish_block (&block);
5598 gfc_init_block (&block);
5599 /* Only if it was repacked. This code needs to be executed before the
5600 loop cleanup code. */
5601 tmp = build_fold_indirect_ref (desc);
5602 tmp = gfc_conv_array_data (tmp);
5603 tmp = fold_build2 (NE_EXPR, boolean_type_node,
5604 fold_convert (TREE_TYPE (tmp), ptr), tmp);
5606 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
5607 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
5608 gfc_conv_expr_present (sym), tmp);
5610 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
5612 gfc_add_expr_to_block (&block, tmp);
5613 gfc_add_block_to_block (&block, &se->post);
5615 gfc_init_block (&se->post);
5616 gfc_add_block_to_block (&se->post, &block);
5621 /* Generate code to deallocate an array, if it is allocated. */
5623 tree
5624 gfc_trans_dealloc_allocated (tree descriptor)
5626 tree tmp;
5627 tree var;
5628 stmtblock_t block;
5630 gfc_start_block (&block);
5632 var = gfc_conv_descriptor_data_get (descriptor);
5633 STRIP_NOPS (var);
5635 /* Call array_deallocate with an int * present in the second argument.
5636 Although it is ignored here, it's presence ensures that arrays that
5637 are already deallocated are ignored. */
5638 tmp = gfc_deallocate_with_status (var, NULL_TREE, true, NULL);
5639 gfc_add_expr_to_block (&block, tmp);
5641 /* Zero the data pointer. */
5642 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
5643 var, build_int_cst (TREE_TYPE (var), 0));
5644 gfc_add_expr_to_block (&block, tmp);
5646 return gfc_finish_block (&block);
5650 /* This helper function calculates the size in words of a full array. */
5652 static tree
5653 get_full_array_size (stmtblock_t *block, tree decl, int rank)
5655 tree idx;
5656 tree nelems;
5657 tree tmp;
5658 idx = gfc_rank_cst[rank - 1];
5659 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
5660 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
5661 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
5662 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
5663 tmp, gfc_index_one_node);
5664 tmp = gfc_evaluate_now (tmp, block);
5666 nelems = gfc_conv_descriptor_stride_get (decl, idx);
5667 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
5668 return gfc_evaluate_now (tmp, block);
5672 /* Allocate dest to the same size as src, and copy src -> dest. */
5674 tree
5675 gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
5677 tree tmp;
5678 tree size;
5679 tree nelems;
5680 tree null_cond;
5681 tree null_data;
5682 stmtblock_t block;
5684 /* If the source is null, set the destination to null. */
5685 gfc_init_block (&block);
5686 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
5687 null_data = gfc_finish_block (&block);
5689 gfc_init_block (&block);
5691 nelems = get_full_array_size (&block, src, rank);
5692 size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
5693 fold_convert (gfc_array_index_type,
5694 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
5696 /* Allocate memory to the destination. */
5697 tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
5698 size);
5699 gfc_conv_descriptor_data_set (&block, dest, tmp);
5701 /* We know the temporary and the value will be the same length,
5702 so can use memcpy. */
5703 tmp = built_in_decls[BUILT_IN_MEMCPY];
5704 tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
5705 gfc_conv_descriptor_data_get (src), size);
5706 gfc_add_expr_to_block (&block, tmp);
5707 tmp = gfc_finish_block (&block);
5709 /* Null the destination if the source is null; otherwise do
5710 the allocate and copy. */
5711 null_cond = gfc_conv_descriptor_data_get (src);
5712 null_cond = convert (pvoid_type_node, null_cond);
5713 null_cond = fold_build2 (NE_EXPR, boolean_type_node,
5714 null_cond, null_pointer_node);
5715 return build3_v (COND_EXPR, null_cond, tmp, null_data);
5719 /* Recursively traverse an object of derived type, generating code to
5720 deallocate, nullify or copy allocatable components. This is the work horse
5721 function for the functions named in this enum. */
5723 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
5725 static tree
5726 structure_alloc_comps (gfc_symbol * der_type, tree decl,
5727 tree dest, int rank, int purpose)
5729 gfc_component *c;
5730 gfc_loopinfo loop;
5731 stmtblock_t fnblock;
5732 stmtblock_t loopbody;
5733 tree tmp;
5734 tree comp;
5735 tree dcmp;
5736 tree nelems;
5737 tree index;
5738 tree var;
5739 tree cdecl;
5740 tree ctype;
5741 tree vref, dref;
5742 tree null_cond = NULL_TREE;
5744 gfc_init_block (&fnblock);
5746 if (POINTER_TYPE_P (TREE_TYPE (decl)))
5747 decl = build_fold_indirect_ref (decl);
5749 /* If this an array of derived types with allocatable components
5750 build a loop and recursively call this function. */
5751 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
5752 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5754 tmp = gfc_conv_array_data (decl);
5755 var = build_fold_indirect_ref (tmp);
5757 /* Get the number of elements - 1 and set the counter. */
5758 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5760 /* Use the descriptor for an allocatable array. Since this
5761 is a full array reference, we only need the descriptor
5762 information from dimension = rank. */
5763 tmp = get_full_array_size (&fnblock, decl, rank);
5764 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
5765 tmp, gfc_index_one_node);
5767 null_cond = gfc_conv_descriptor_data_get (decl);
5768 null_cond = fold_build2 (NE_EXPR, boolean_type_node, null_cond,
5769 build_int_cst (TREE_TYPE (null_cond), 0));
5771 else
5773 /* Otherwise use the TYPE_DOMAIN information. */
5774 tmp = array_type_nelts (TREE_TYPE (decl));
5775 tmp = fold_convert (gfc_array_index_type, tmp);
5778 /* Remember that this is, in fact, the no. of elements - 1. */
5779 nelems = gfc_evaluate_now (tmp, &fnblock);
5780 index = gfc_create_var (gfc_array_index_type, "S");
5782 /* Build the body of the loop. */
5783 gfc_init_block (&loopbody);
5785 vref = gfc_build_array_ref (var, index, NULL);
5787 if (purpose == COPY_ALLOC_COMP)
5789 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
5791 tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
5792 gfc_add_expr_to_block (&fnblock, tmp);
5794 tmp = build_fold_indirect_ref (gfc_conv_array_data (dest));
5795 dref = gfc_build_array_ref (tmp, index, NULL);
5796 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
5798 else
5799 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
5801 gfc_add_expr_to_block (&loopbody, tmp);
5803 /* Build the loop and return. */
5804 gfc_init_loopinfo (&loop);
5805 loop.dimen = 1;
5806 loop.from[0] = gfc_index_zero_node;
5807 loop.loopvar[0] = index;
5808 loop.to[0] = nelems;
5809 gfc_trans_scalarizing_loops (&loop, &loopbody);
5810 gfc_add_block_to_block (&fnblock, &loop.pre);
5812 tmp = gfc_finish_block (&fnblock);
5813 if (null_cond != NULL_TREE)
5814 tmp = build3_v (COND_EXPR, null_cond, tmp,
5815 build_empty_stmt (input_location));
5817 return tmp;
5820 /* Otherwise, act on the components or recursively call self to
5821 act on a chain of components. */
5822 for (c = der_type->components; c; c = c->next)
5824 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
5825 && c->ts.derived->attr.alloc_comp;
5826 cdecl = c->backend_decl;
5827 ctype = TREE_TYPE (cdecl);
5829 switch (purpose)
5831 case DEALLOCATE_ALLOC_COMP:
5832 /* Do not deallocate the components of ultimate pointer
5833 components. */
5834 if (cmp_has_alloc_comps && !c->attr.pointer)
5836 comp = fold_build3 (COMPONENT_REF, ctype,
5837 decl, cdecl, NULL_TREE);
5838 rank = c->as ? c->as->rank : 0;
5839 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5840 rank, purpose);
5841 gfc_add_expr_to_block (&fnblock, tmp);
5844 if (c->attr.allocatable)
5846 comp = fold_build3 (COMPONENT_REF, ctype,
5847 decl, cdecl, NULL_TREE);
5848 tmp = gfc_trans_dealloc_allocated (comp);
5849 gfc_add_expr_to_block (&fnblock, tmp);
5851 break;
5853 case NULLIFY_ALLOC_COMP:
5854 if (c->attr.pointer)
5855 continue;
5856 else if (c->attr.allocatable)
5858 comp = fold_build3 (COMPONENT_REF, ctype,
5859 decl, cdecl, NULL_TREE);
5860 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
5862 else if (cmp_has_alloc_comps)
5864 comp = fold_build3 (COMPONENT_REF, ctype,
5865 decl, cdecl, NULL_TREE);
5866 rank = c->as ? c->as->rank : 0;
5867 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5868 rank, purpose);
5869 gfc_add_expr_to_block (&fnblock, tmp);
5871 break;
5873 case COPY_ALLOC_COMP:
5874 if (c->attr.pointer)
5875 continue;
5877 /* We need source and destination components. */
5878 comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5879 dcmp = fold_build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
5880 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
5882 if (c->attr.allocatable && !cmp_has_alloc_comps)
5884 tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
5885 gfc_add_expr_to_block (&fnblock, tmp);
5888 if (cmp_has_alloc_comps)
5890 rank = c->as ? c->as->rank : 0;
5891 tmp = fold_convert (TREE_TYPE (dcmp), comp);
5892 gfc_add_modify (&fnblock, dcmp, tmp);
5893 tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
5894 rank, purpose);
5895 gfc_add_expr_to_block (&fnblock, tmp);
5897 break;
5899 default:
5900 gcc_unreachable ();
5901 break;
5905 return gfc_finish_block (&fnblock);
5908 /* Recursively traverse an object of derived type, generating code to
5909 nullify allocatable components. */
5911 tree
5912 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5914 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5915 NULLIFY_ALLOC_COMP);
5919 /* Recursively traverse an object of derived type, generating code to
5920 deallocate allocatable components. */
5922 tree
5923 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5925 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5926 DEALLOCATE_ALLOC_COMP);
5930 /* Recursively traverse an object of derived type, generating code to
5931 copy its allocatable components. */
5933 tree
5934 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
5936 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
5940 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
5941 Do likewise, recursively if necessary, with the allocatable components of
5942 derived types. */
5944 tree
5945 gfc_trans_deferred_array (gfc_symbol * sym, tree body)
5947 tree type;
5948 tree tmp;
5949 tree descriptor;
5950 stmtblock_t fnblock;
5951 locus loc;
5952 int rank;
5953 bool sym_has_alloc_comp;
5955 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
5956 && sym->ts.derived->attr.alloc_comp;
5958 /* Make sure the frontend gets these right. */
5959 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
5960 fatal_error ("Possible frontend bug: Deferred array size without pointer, "
5961 "allocatable attribute or derived type without allocatable "
5962 "components.");
5964 gfc_init_block (&fnblock);
5966 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
5967 || TREE_CODE (sym->backend_decl) == PARM_DECL);
5969 if (sym->ts.type == BT_CHARACTER
5970 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
5972 gfc_conv_string_length (sym->ts.cl, NULL, &fnblock);
5973 gfc_trans_vla_type_sizes (sym, &fnblock);
5976 /* Dummy, use associated and result variables don't need anything special. */
5977 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
5979 gfc_add_expr_to_block (&fnblock, body);
5981 return gfc_finish_block (&fnblock);
5984 gfc_get_backend_locus (&loc);
5985 gfc_set_backend_locus (&sym->declared_at);
5986 descriptor = sym->backend_decl;
5988 /* Although static, derived types with default initializers and
5989 allocatable components must not be nulled wholesale; instead they
5990 are treated component by component. */
5991 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
5993 /* SAVEd variables are not freed on exit. */
5994 gfc_trans_static_array_pointer (sym);
5995 return body;
5998 /* Get the descriptor type. */
5999 type = TREE_TYPE (sym->backend_decl);
6001 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
6003 if (!sym->attr.save)
6005 rank = sym->as ? sym->as->rank : 0;
6006 tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
6007 gfc_add_expr_to_block (&fnblock, tmp);
6008 if (sym->value)
6010 tmp = gfc_init_default_dt (sym, NULL);
6011 gfc_add_expr_to_block (&fnblock, tmp);
6015 else if (!GFC_DESCRIPTOR_TYPE_P (type))
6017 /* If the backend_decl is not a descriptor, we must have a pointer
6018 to one. */
6019 descriptor = build_fold_indirect_ref (sym->backend_decl);
6020 type = TREE_TYPE (descriptor);
6023 /* NULLIFY the data pointer. */
6024 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
6025 gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
6027 gfc_add_expr_to_block (&fnblock, body);
6029 gfc_set_backend_locus (&loc);
6031 /* Allocatable arrays need to be freed when they go out of scope.
6032 The allocatable components of pointers must not be touched. */
6033 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
6034 && !sym->attr.pointer && !sym->attr.save)
6036 int rank;
6037 rank = sym->as ? sym->as->rank : 0;
6038 tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
6039 gfc_add_expr_to_block (&fnblock, tmp);
6042 if (sym->attr.allocatable && !sym->attr.save && !sym->attr.result)
6044 tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
6045 gfc_add_expr_to_block (&fnblock, tmp);
6048 return gfc_finish_block (&fnblock);
6051 /************ Expression Walking Functions ******************/
6053 /* Walk a variable reference.
6055 Possible extension - multiple component subscripts.
6056 x(:,:) = foo%a(:)%b(:)
6057 Transforms to
6058 forall (i=..., j=...)
6059 x(i,j) = foo%a(j)%b(i)
6060 end forall
6061 This adds a fair amount of complexity because you need to deal with more
6062 than one ref. Maybe handle in a similar manner to vector subscripts.
6063 Maybe not worth the effort. */
6066 static gfc_ss *
6067 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
6069 gfc_ref *ref;
6070 gfc_array_ref *ar;
6071 gfc_ss *newss;
6072 gfc_ss *head;
6073 int n;
6075 for (ref = expr->ref; ref; ref = ref->next)
6076 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
6077 break;
6079 for (; ref; ref = ref->next)
6081 if (ref->type == REF_SUBSTRING)
6083 newss = gfc_get_ss ();
6084 newss->type = GFC_SS_SCALAR;
6085 newss->expr = ref->u.ss.start;
6086 newss->next = ss;
6087 ss = newss;
6089 newss = gfc_get_ss ();
6090 newss->type = GFC_SS_SCALAR;
6091 newss->expr = ref->u.ss.end;
6092 newss->next = ss;
6093 ss = newss;
6096 /* We're only interested in array sections from now on. */
6097 if (ref->type != REF_ARRAY)
6098 continue;
6100 ar = &ref->u.ar;
6101 switch (ar->type)
6103 case AR_ELEMENT:
6104 for (n = 0; n < ar->dimen; n++)
6106 newss = gfc_get_ss ();
6107 newss->type = GFC_SS_SCALAR;
6108 newss->expr = ar->start[n];
6109 newss->next = ss;
6110 ss = newss;
6112 break;
6114 case AR_FULL:
6115 newss = gfc_get_ss ();
6116 newss->type = GFC_SS_SECTION;
6117 newss->expr = expr;
6118 newss->next = ss;
6119 newss->data.info.dimen = ar->as->rank;
6120 newss->data.info.ref = ref;
6122 /* Make sure array is the same as array(:,:), this way
6123 we don't need to special case all the time. */
6124 ar->dimen = ar->as->rank;
6125 for (n = 0; n < ar->dimen; n++)
6127 newss->data.info.dim[n] = n;
6128 ar->dimen_type[n] = DIMEN_RANGE;
6130 gcc_assert (ar->start[n] == NULL);
6131 gcc_assert (ar->end[n] == NULL);
6132 gcc_assert (ar->stride[n] == NULL);
6134 ss = newss;
6135 break;
6137 case AR_SECTION:
6138 newss = gfc_get_ss ();
6139 newss->type = GFC_SS_SECTION;
6140 newss->expr = expr;
6141 newss->next = ss;
6142 newss->data.info.dimen = 0;
6143 newss->data.info.ref = ref;
6145 head = newss;
6147 /* We add SS chains for all the subscripts in the section. */
6148 for (n = 0; n < ar->dimen; n++)
6150 gfc_ss *indexss;
6152 switch (ar->dimen_type[n])
6154 case DIMEN_ELEMENT:
6155 /* Add SS for elemental (scalar) subscripts. */
6156 gcc_assert (ar->start[n]);
6157 indexss = gfc_get_ss ();
6158 indexss->type = GFC_SS_SCALAR;
6159 indexss->expr = ar->start[n];
6160 indexss->next = gfc_ss_terminator;
6161 indexss->loop_chain = gfc_ss_terminator;
6162 newss->data.info.subscript[n] = indexss;
6163 break;
6165 case DIMEN_RANGE:
6166 /* We don't add anything for sections, just remember this
6167 dimension for later. */
6168 newss->data.info.dim[newss->data.info.dimen] = n;
6169 newss->data.info.dimen++;
6170 break;
6172 case DIMEN_VECTOR:
6173 /* Create a GFC_SS_VECTOR index in which we can store
6174 the vector's descriptor. */
6175 indexss = gfc_get_ss ();
6176 indexss->type = GFC_SS_VECTOR;
6177 indexss->expr = ar->start[n];
6178 indexss->next = gfc_ss_terminator;
6179 indexss->loop_chain = gfc_ss_terminator;
6180 newss->data.info.subscript[n] = indexss;
6181 newss->data.info.dim[newss->data.info.dimen] = n;
6182 newss->data.info.dimen++;
6183 break;
6185 default:
6186 /* We should know what sort of section it is by now. */
6187 gcc_unreachable ();
6190 /* We should have at least one non-elemental dimension. */
6191 gcc_assert (newss->data.info.dimen > 0);
6192 ss = newss;
6193 break;
6195 default:
6196 /* We should know what sort of section it is by now. */
6197 gcc_unreachable ();
6201 return ss;
6205 /* Walk an expression operator. If only one operand of a binary expression is
6206 scalar, we must also add the scalar term to the SS chain. */
6208 static gfc_ss *
6209 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
6211 gfc_ss *head;
6212 gfc_ss *head2;
6213 gfc_ss *newss;
6215 head = gfc_walk_subexpr (ss, expr->value.op.op1);
6216 if (expr->value.op.op2 == NULL)
6217 head2 = head;
6218 else
6219 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
6221 /* All operands are scalar. Pass back and let the caller deal with it. */
6222 if (head2 == ss)
6223 return head2;
6225 /* All operands require scalarization. */
6226 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
6227 return head2;
6229 /* One of the operands needs scalarization, the other is scalar.
6230 Create a gfc_ss for the scalar expression. */
6231 newss = gfc_get_ss ();
6232 newss->type = GFC_SS_SCALAR;
6233 if (head == ss)
6235 /* First operand is scalar. We build the chain in reverse order, so
6236 add the scalar SS after the second operand. */
6237 head = head2;
6238 while (head && head->next != ss)
6239 head = head->next;
6240 /* Check we haven't somehow broken the chain. */
6241 gcc_assert (head);
6242 newss->next = ss;
6243 head->next = newss;
6244 newss->expr = expr->value.op.op1;
6246 else /* head2 == head */
6248 gcc_assert (head2 == head);
6249 /* Second operand is scalar. */
6250 newss->next = head2;
6251 head2 = newss;
6252 newss->expr = expr->value.op.op2;
6255 return head2;
6259 /* Reverse a SS chain. */
6261 gfc_ss *
6262 gfc_reverse_ss (gfc_ss * ss)
6264 gfc_ss *next;
6265 gfc_ss *head;
6267 gcc_assert (ss != NULL);
6269 head = gfc_ss_terminator;
6270 while (ss != gfc_ss_terminator)
6272 next = ss->next;
6273 /* Check we didn't somehow break the chain. */
6274 gcc_assert (next != NULL);
6275 ss->next = head;
6276 head = ss;
6277 ss = next;
6280 return (head);
6284 /* Walk the arguments of an elemental function. */
6286 gfc_ss *
6287 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
6288 gfc_ss_type type)
6290 int scalar;
6291 gfc_ss *head;
6292 gfc_ss *tail;
6293 gfc_ss *newss;
6295 head = gfc_ss_terminator;
6296 tail = NULL;
6297 scalar = 1;
6298 for (; arg; arg = arg->next)
6300 if (!arg->expr)
6301 continue;
6303 newss = gfc_walk_subexpr (head, arg->expr);
6304 if (newss == head)
6306 /* Scalar argument. */
6307 newss = gfc_get_ss ();
6308 newss->type = type;
6309 newss->expr = arg->expr;
6310 newss->next = head;
6312 else
6313 scalar = 0;
6315 head = newss;
6316 if (!tail)
6318 tail = head;
6319 while (tail->next != gfc_ss_terminator)
6320 tail = tail->next;
6324 if (scalar)
6326 /* If all the arguments are scalar we don't need the argument SS. */
6327 gfc_free_ss_chain (head);
6328 /* Pass it back. */
6329 return ss;
6332 /* Add it onto the existing chain. */
6333 tail->next = ss;
6334 return head;
6338 /* Walk a function call. Scalar functions are passed back, and taken out of
6339 scalarization loops. For elemental functions we walk their arguments.
6340 The result of functions returning arrays is stored in a temporary outside
6341 the loop, so that the function is only called once. Hence we do not need
6342 to walk their arguments. */
6344 static gfc_ss *
6345 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
6347 gfc_ss *newss;
6348 gfc_intrinsic_sym *isym;
6349 gfc_symbol *sym;
6350 gfc_component *comp = NULL;
6352 isym = expr->value.function.isym;
6354 /* Handle intrinsic functions separately. */
6355 if (isym)
6356 return gfc_walk_intrinsic_function (ss, expr, isym);
6358 sym = expr->value.function.esym;
6359 if (!sym)
6360 sym = expr->symtree->n.sym;
6362 /* A function that returns arrays. */
6363 is_proc_ptr_comp (expr, &comp);
6364 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
6365 || (comp && comp->attr.dimension))
6367 newss = gfc_get_ss ();
6368 newss->type = GFC_SS_FUNCTION;
6369 newss->expr = expr;
6370 newss->next = ss;
6371 newss->data.info.dimen = expr->rank;
6372 return newss;
6375 /* Walk the parameters of an elemental function. For now we always pass
6376 by reference. */
6377 if (sym->attr.elemental)
6378 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
6379 GFC_SS_REFERENCE);
6381 /* Scalar functions are OK as these are evaluated outside the scalarization
6382 loop. Pass back and let the caller deal with it. */
6383 return ss;
6387 /* An array temporary is constructed for array constructors. */
6389 static gfc_ss *
6390 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
6392 gfc_ss *newss;
6393 int n;
6395 newss = gfc_get_ss ();
6396 newss->type = GFC_SS_CONSTRUCTOR;
6397 newss->expr = expr;
6398 newss->next = ss;
6399 newss->data.info.dimen = expr->rank;
6400 for (n = 0; n < expr->rank; n++)
6401 newss->data.info.dim[n] = n;
6403 return newss;
6407 /* Walk an expression. Add walked expressions to the head of the SS chain.
6408 A wholly scalar expression will not be added. */
6410 static gfc_ss *
6411 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
6413 gfc_ss *head;
6415 switch (expr->expr_type)
6417 case EXPR_VARIABLE:
6418 head = gfc_walk_variable_expr (ss, expr);
6419 return head;
6421 case EXPR_OP:
6422 head = gfc_walk_op_expr (ss, expr);
6423 return head;
6425 case EXPR_FUNCTION:
6426 head = gfc_walk_function_expr (ss, expr);
6427 return head;
6429 case EXPR_CONSTANT:
6430 case EXPR_NULL:
6431 case EXPR_STRUCTURE:
6432 /* Pass back and let the caller deal with it. */
6433 break;
6435 case EXPR_ARRAY:
6436 head = gfc_walk_array_constructor (ss, expr);
6437 return head;
6439 case EXPR_SUBSTRING:
6440 /* Pass back and let the caller deal with it. */
6441 break;
6443 default:
6444 internal_error ("bad expression type during walk (%d)",
6445 expr->expr_type);
6447 return ss;
6451 /* Entry point for expression walking.
6452 A return value equal to the passed chain means this is
6453 a scalar expression. It is up to the caller to take whatever action is
6454 necessary to translate these. */
6456 gfc_ss *
6457 gfc_walk_expr (gfc_expr * expr)
6459 gfc_ss *res;
6461 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
6462 return gfc_reverse_ss (res);