1 /* Array translation routines
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
4 Free Software Foundation, Inc.
5 Contributed by Paul Brook <paul@nowt.org>
6 and Steven Bosscher <s.bosscher@student.tudelft.nl>
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 /* trans-array.c-- Various array related code, including scalarization,
25 allocation, initialization and other support routines. */
27 /* How the scalarizer works.
28 In gfortran, array expressions use the same core routines as scalar
30 First, a Scalarization State (SS) chain is built. This is done by walking
31 the expression tree, and building a linear list of the terms in the
32 expression. As the tree is walked, scalar subexpressions are translated.
34 The scalarization parameters are stored in a gfc_loopinfo structure.
35 First the start and stride of each term is calculated by
36 gfc_conv_ss_startstride. During this process the expressions for the array
37 descriptors and data pointers are also translated.
39 If the expression is an assignment, we must then resolve any dependencies.
40 In fortran all the rhs values of an assignment must be evaluated before
41 any assignments take place. This can require a temporary array to store the
42 values. We also require a temporary when we are passing array expressions
43 or vector subscripts as procedure parameters.
45 Array sections are passed without copying to a temporary. These use the
46 scalarizer to determine the shape of the section. The flag
47 loop->array_parameter tells the scalarizer that the actual values and loop
48 variables will not be required.
50 The function gfc_conv_loop_setup generates the scalarization setup code.
51 It determines the range of the scalarizing loop variables. If a temporary
52 is required, this is created and initialized. Code for scalar expressions
53 taken outside the loop is also generated at this time. Next the offset and
54 scaling required to translate from loop variables to array indices for each
57 A call to gfc_start_scalarized_body marks the start of the scalarized
58 expression. This creates a scope and declares the loop variables. Before
59 calling this gfc_make_ss_chain_used must be used to indicate which terms
60 will be used inside this loop.
62 The scalar gfc_conv_* functions are then used to build the main body of the
63 scalarization loop. Scalarization loop variables and precalculated scalar
64 values are automatically substituted. Note that gfc_advance_se_ss_chain
65 must be used, rather than changing the se->ss directly.
67 For assignment expressions requiring a temporary two sub loops are
68 generated. The first stores the result of the expression in the temporary,
69 the second copies it to the result. A call to
70 gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
71 the start of the copying loop. The temporary may be less than full rank.
73 Finally gfc_trans_scalarizing_loops is called to generate the implicit do
74 loops. The loops are added to the pre chain of the loopinfo. The post
75 chain may still contain cleanup code.
77 After the loop code has been added into its parent scope gfc_cleanup_loop
78 is called to free all the SS allocated by the scalarizer. */
82 #include "coretypes.h"
85 #include "diagnostic-core.h" /* For internal_error/fatal_error. */
88 #include "constructor.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 bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
98 /* The contents of this structure aren't actually used, just the address. */
99 static gfc_ss gfc_ss_terminator_var;
100 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
104 gfc_array_dataptr_type (tree desc)
106 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
110 /* Build expressions to access the members of an array descriptor.
111 It's surprisingly easy to mess up here, so never access
112 an array descriptor by "brute force", always use these
113 functions. This also avoids problems if we change the format
114 of an array descriptor.
116 To understand these magic numbers, look at the comments
117 before gfc_build_array_type() in trans-types.c.
119 The code within these defines should be the only code which knows the format
120 of an array descriptor.
122 Any code just needing to read obtain the bounds of an array should use
123 gfc_conv_array_* rather than the following functions as these will return
124 know constant values, and work with arrays which do not have descriptors.
126 Don't forget to #undef these! */
129 #define OFFSET_FIELD 1
130 #define DTYPE_FIELD 2
131 #define DIMENSION_FIELD 3
132 #define CAF_TOKEN_FIELD 4
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. */
142 gfc_conv_descriptor_data_get (tree desc)
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_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
154 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
159 /* This provides WRITE access to the data field.
161 TUPLES_P is true if we are generating tuples.
163 This function gets called through the following macros:
164 gfc_conv_descriptor_data_set
165 gfc_conv_descriptor_data_set. */
168 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
172 type = TREE_TYPE (desc);
173 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
175 field = TYPE_FIELDS (type);
176 gcc_assert (DATA_FIELD == 0);
178 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
180 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
184 /* This provides address access to the data field. This should only be
185 used by array allocation, passing this on to the runtime. */
188 gfc_conv_descriptor_data_addr (tree desc)
192 type = TREE_TYPE (desc);
193 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
195 field = TYPE_FIELDS (type);
196 gcc_assert (DATA_FIELD == 0);
198 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
200 return gfc_build_addr_expr (NULL_TREE, t);
204 gfc_conv_descriptor_offset (tree desc)
209 type = TREE_TYPE (desc);
210 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
212 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
213 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
215 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
216 desc, field, NULL_TREE);
220 gfc_conv_descriptor_offset_get (tree desc)
222 return gfc_conv_descriptor_offset (desc);
226 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
229 tree t = gfc_conv_descriptor_offset (desc);
230 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
235 gfc_conv_descriptor_dtype (tree desc)
240 type = TREE_TYPE (desc);
241 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
243 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
244 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
246 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
247 desc, field, NULL_TREE);
251 gfc_conv_descriptor_dimension (tree desc, tree dim)
257 type = TREE_TYPE (desc);
258 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
260 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
261 gcc_assert (field != NULL_TREE
262 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
263 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
265 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
266 desc, field, NULL_TREE);
267 tmp = gfc_build_array_ref (tmp, dim, NULL);
273 gfc_conv_descriptor_token (tree desc)
278 type = TREE_TYPE (desc);
279 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
280 gcc_assert (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE);
281 gcc_assert (gfc_option.coarray == GFC_FCOARRAY_LIB);
282 field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
283 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == prvoid_type_node);
285 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
286 desc, field, NULL_TREE);
291 gfc_conv_descriptor_stride (tree desc, tree dim)
296 tmp = gfc_conv_descriptor_dimension (desc, dim);
297 field = TYPE_FIELDS (TREE_TYPE (tmp));
298 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
299 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
301 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
302 tmp, field, NULL_TREE);
307 gfc_conv_descriptor_stride_get (tree desc, tree dim)
309 tree type = TREE_TYPE (desc);
310 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
311 if (integer_zerop (dim)
312 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
313 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
314 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
315 return gfc_index_one_node;
317 return gfc_conv_descriptor_stride (desc, dim);
321 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
322 tree dim, tree value)
324 tree t = gfc_conv_descriptor_stride (desc, dim);
325 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
329 gfc_conv_descriptor_lbound (tree desc, tree dim)
334 tmp = gfc_conv_descriptor_dimension (desc, dim);
335 field = TYPE_FIELDS (TREE_TYPE (tmp));
336 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
337 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
339 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
340 tmp, field, NULL_TREE);
345 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
347 return gfc_conv_descriptor_lbound (desc, dim);
351 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
352 tree dim, tree value)
354 tree t = gfc_conv_descriptor_lbound (desc, dim);
355 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
359 gfc_conv_descriptor_ubound (tree desc, tree dim)
364 tmp = gfc_conv_descriptor_dimension (desc, dim);
365 field = TYPE_FIELDS (TREE_TYPE (tmp));
366 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
367 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
369 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
370 tmp, field, NULL_TREE);
375 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
377 return gfc_conv_descriptor_ubound (desc, dim);
381 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
382 tree dim, tree value)
384 tree t = gfc_conv_descriptor_ubound (desc, dim);
385 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
388 /* Build a null array descriptor constructor. */
391 gfc_build_null_descriptor (tree type)
396 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
397 gcc_assert (DATA_FIELD == 0);
398 field = TYPE_FIELDS (type);
400 /* Set a NULL data pointer. */
401 tmp = build_constructor_single (type, field, null_pointer_node);
402 TREE_CONSTANT (tmp) = 1;
403 /* All other fields are ignored. */
409 /* Modify a descriptor such that the lbound of a given dimension is the value
410 specified. This also updates ubound and offset accordingly. */
413 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
414 int dim, tree new_lbound)
416 tree offs, ubound, lbound, stride;
417 tree diff, offs_diff;
419 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
421 offs = gfc_conv_descriptor_offset_get (desc);
422 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
423 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
424 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
426 /* Get difference (new - old) by which to shift stuff. */
427 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
430 /* Shift ubound and offset accordingly. This has to be done before
431 updating the lbound, as they depend on the lbound expression! */
432 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
434 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
435 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
437 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
439 gfc_conv_descriptor_offset_set (block, desc, offs);
441 /* Finally set lbound to value we want. */
442 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
446 /* Cleanup those #defines. */
451 #undef DIMENSION_FIELD
452 #undef CAF_TOKEN_FIELD
453 #undef STRIDE_SUBFIELD
454 #undef LBOUND_SUBFIELD
455 #undef UBOUND_SUBFIELD
458 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
459 flags & 1 = Main loop body.
460 flags & 2 = temp copy loop. */
463 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
465 for (; ss != gfc_ss_terminator; ss = ss->next)
466 ss->info->useflags = flags;
469 static void gfc_free_ss (gfc_ss *);
472 /* Free a gfc_ss chain. */
475 gfc_free_ss_chain (gfc_ss * ss)
479 while (ss != gfc_ss_terminator)
481 gcc_assert (ss != NULL);
490 free_ss_info (gfc_ss_info *ss_info)
493 if (ss_info->refcount > 0)
496 gcc_assert (ss_info->refcount == 0);
504 gfc_free_ss (gfc_ss * ss)
506 gfc_ss_info *ss_info;
511 switch (ss_info->type)
514 for (n = 0; n < ss->dimen; n++)
516 if (ss_info->data.array.subscript[ss->dim[n]])
517 gfc_free_ss_chain (ss_info->data.array.subscript[ss->dim[n]]);
525 free_ss_info (ss_info);
530 /* Creates and initializes an array type gfc_ss struct. */
533 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
536 gfc_ss_info *ss_info;
539 ss_info = gfc_get_ss_info ();
541 ss_info->type = type;
542 ss_info->expr = expr;
548 for (i = 0; i < ss->dimen; i++)
555 /* Creates and initializes a temporary type gfc_ss struct. */
558 gfc_get_temp_ss (tree type, tree string_length, int dimen)
561 gfc_ss_info *ss_info;
564 ss_info = gfc_get_ss_info ();
566 ss_info->type = GFC_SS_TEMP;
567 ss_info->string_length = string_length;
568 ss_info->data.temp.type = type;
572 ss->next = gfc_ss_terminator;
574 for (i = 0; i < ss->dimen; i++)
581 /* Creates and initializes a scalar type gfc_ss struct. */
584 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
587 gfc_ss_info *ss_info;
589 ss_info = gfc_get_ss_info ();
591 ss_info->type = GFC_SS_SCALAR;
592 ss_info->expr = expr;
602 /* Free all the SS associated with a loop. */
605 gfc_cleanup_loop (gfc_loopinfo * loop)
611 while (ss != gfc_ss_terminator)
613 gcc_assert (ss != NULL);
614 next = ss->loop_chain;
622 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
626 for (; ss != gfc_ss_terminator; ss = ss->next)
630 if (ss->info->type == GFC_SS_SCALAR
631 || ss->info->type == GFC_SS_REFERENCE
632 || ss->info->type == GFC_SS_TEMP)
635 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
636 if (ss->info->data.array.subscript[n] != NULL)
637 set_ss_loop (ss->info->data.array.subscript[n], loop);
642 /* Associate a SS chain with a loop. */
645 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
649 if (head == gfc_ss_terminator)
652 set_ss_loop (head, loop);
655 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
657 if (ss->next == gfc_ss_terminator)
658 ss->loop_chain = loop->ss;
660 ss->loop_chain = ss->next;
662 gcc_assert (ss == gfc_ss_terminator);
667 /* Generate an initializer for a static pointer or allocatable array. */
670 gfc_trans_static_array_pointer (gfc_symbol * sym)
674 gcc_assert (TREE_STATIC (sym->backend_decl));
675 /* Just zero the data member. */
676 type = TREE_TYPE (sym->backend_decl);
677 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
681 /* If the bounds of SE's loop have not yet been set, see if they can be
682 determined from array spec AS, which is the array spec of a called
683 function. MAPPING maps the callee's dummy arguments to the values
684 that the caller is passing. Add any initialization and finalization
688 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
689 gfc_se * se, gfc_array_spec * as)
691 int n, dim, total_dim;
700 if (!as || as->type != AS_EXPLICIT)
703 for (ss = se->ss; ss; ss = ss->parent)
705 total_dim += ss->loop->dimen;
706 for (n = 0; n < ss->loop->dimen; n++)
708 /* The bound is known, nothing to do. */
709 if (ss->loop->to[n] != NULL_TREE)
713 gcc_assert (dim < as->rank);
714 gcc_assert (ss->loop->dimen <= as->rank);
716 /* Evaluate the lower bound. */
717 gfc_init_se (&tmpse, NULL);
718 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
719 gfc_add_block_to_block (&se->pre, &tmpse.pre);
720 gfc_add_block_to_block (&se->post, &tmpse.post);
721 lower = fold_convert (gfc_array_index_type, tmpse.expr);
723 /* ...and the upper bound. */
724 gfc_init_se (&tmpse, NULL);
725 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
726 gfc_add_block_to_block (&se->pre, &tmpse.pre);
727 gfc_add_block_to_block (&se->post, &tmpse.post);
728 upper = fold_convert (gfc_array_index_type, tmpse.expr);
730 /* Set the upper bound of the loop to UPPER - LOWER. */
731 tmp = fold_build2_loc (input_location, MINUS_EXPR,
732 gfc_array_index_type, upper, lower);
733 tmp = gfc_evaluate_now (tmp, &se->pre);
734 ss->loop->to[n] = tmp;
738 gcc_assert (total_dim == as->rank);
742 /* Generate code to allocate an array temporary, or create a variable to
743 hold the data. If size is NULL, zero the descriptor so that the
744 callee will allocate the array. If DEALLOC is true, also generate code to
745 free the array afterwards.
747 If INITIAL is not NULL, it is packed using internal_pack and the result used
748 as data instead of allocating a fresh, unitialized area of memory.
750 Initialization code is added to PRE and finalization code to POST.
751 DYNAMIC is true if the caller may want to extend the array later
752 using realloc. This prevents us from putting the array on the stack. */
755 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
756 gfc_array_info * info, tree size, tree nelem,
757 tree initial, bool dynamic, bool dealloc)
763 desc = info->descriptor;
764 info->offset = gfc_index_zero_node;
765 if (size == NULL_TREE || integer_zerop (size))
767 /* A callee allocated array. */
768 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
773 /* Allocate the temporary. */
774 onstack = !dynamic && initial == NULL_TREE
775 && (gfc_option.flag_stack_arrays
776 || gfc_can_put_var_on_stack (size));
780 /* Make a temporary variable to hold the data. */
781 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
782 nelem, gfc_index_one_node);
783 tmp = gfc_evaluate_now (tmp, pre);
784 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
786 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
788 tmp = gfc_create_var (tmp, "A");
789 /* If we're here only because of -fstack-arrays we have to
790 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
791 if (!gfc_can_put_var_on_stack (size))
792 gfc_add_expr_to_block (pre,
793 fold_build1_loc (input_location,
794 DECL_EXPR, TREE_TYPE (tmp),
796 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
797 gfc_conv_descriptor_data_set (pre, desc, tmp);
801 /* Allocate memory to hold the data or call internal_pack. */
802 if (initial == NULL_TREE)
804 tmp = gfc_call_malloc (pre, NULL, size);
805 tmp = gfc_evaluate_now (tmp, pre);
812 stmtblock_t do_copying;
814 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
815 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
816 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
817 tmp = gfc_get_element_type (tmp);
818 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
819 packed = gfc_create_var (build_pointer_type (tmp), "data");
821 tmp = build_call_expr_loc (input_location,
822 gfor_fndecl_in_pack, 1, initial);
823 tmp = fold_convert (TREE_TYPE (packed), tmp);
824 gfc_add_modify (pre, packed, tmp);
826 tmp = build_fold_indirect_ref_loc (input_location,
828 source_data = gfc_conv_descriptor_data_get (tmp);
830 /* internal_pack may return source->data without any allocation
831 or copying if it is already packed. If that's the case, we
832 need to allocate and copy manually. */
834 gfc_start_block (&do_copying);
835 tmp = gfc_call_malloc (&do_copying, NULL, size);
836 tmp = fold_convert (TREE_TYPE (packed), tmp);
837 gfc_add_modify (&do_copying, packed, tmp);
838 tmp = gfc_build_memcpy_call (packed, source_data, size);
839 gfc_add_expr_to_block (&do_copying, tmp);
841 was_packed = fold_build2_loc (input_location, EQ_EXPR,
842 boolean_type_node, packed,
844 tmp = gfc_finish_block (&do_copying);
845 tmp = build3_v (COND_EXPR, was_packed, tmp,
846 build_empty_stmt (input_location));
847 gfc_add_expr_to_block (pre, tmp);
849 tmp = fold_convert (pvoid_type_node, packed);
852 gfc_conv_descriptor_data_set (pre, desc, tmp);
855 info->data = gfc_conv_descriptor_data_get (desc);
857 /* The offset is zero because we create temporaries with a zero
859 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
861 if (dealloc && !onstack)
863 /* Free the temporary. */
864 tmp = gfc_conv_descriptor_data_get (desc);
865 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
866 gfc_add_expr_to_block (post, tmp);
871 /* Get the scalarizer array dimension corresponding to actual array dimension
874 For example, if SS represents the array ref a(1,:,:,1), it is a
875 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
876 and 1 for ARRAY_DIM=2.
877 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
878 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
880 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
881 array. If called on the inner ss, the result would be respectively 0,1,2 for
882 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
883 for ARRAY_DIM=1,2. */
886 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
893 for (; ss; ss = ss->parent)
894 for (n = 0; n < ss->dimen; n++)
895 if (ss->dim[n] < array_dim)
898 return array_ref_dim;
903 innermost_ss (gfc_ss *ss)
905 while (ss->nested_ss != NULL)
913 /* Get the array reference dimension corresponding to the given loop dimension.
914 It is different from the true array dimension given by the dim array in
915 the case of a partial array reference (i.e. a(:,:,1,:) for example)
916 It is different from the loop dimension in the case of a transposed array.
920 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
922 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
927 /* Generate code to create and initialize the descriptor for a temporary
928 array. This is used for both temporaries needed by the scalarizer, and
929 functions returning arrays. Adjusts the loop variables to be
930 zero-based, and calculates the loop bounds for callee allocated arrays.
931 Allocate the array unless it's callee allocated (we have a callee
932 allocated array if 'callee_alloc' is true, or if loop->to[n] is
933 NULL_TREE for any n). Also fills in the descriptor, data and offset
934 fields of info if known. Returns the size of the array, or NULL for a
935 callee allocated array.
937 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
938 gfc_trans_allocate_array_storage. */
941 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
942 tree eltype, tree initial, bool dynamic,
943 bool dealloc, bool callee_alloc, locus * where)
946 gfc_array_info *info;
947 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
958 memset (from, 0, sizeof (from));
959 memset (to, 0, sizeof (to));
961 info = &ss->info->data.array;
963 gcc_assert (ss->dimen > 0);
964 gcc_assert (ss->loop->dimen == ss->dimen);
966 if (gfc_option.warn_array_temp && where)
967 gfc_warning ("Creating array temporary at %L", where);
970 total_dim = loop->dimen;
971 /* Set the lower bound to zero. */
972 for (n = 0; n < loop->dimen; n++)
976 /* Callee allocated arrays may not have a known bound yet. */
978 loop->to[n] = gfc_evaluate_now (
979 fold_build2_loc (input_location, MINUS_EXPR,
980 gfc_array_index_type,
981 loop->to[n], loop->from[n]),
983 loop->from[n] = gfc_index_zero_node;
985 /* We have just changed the loop bounds, we must clear the
986 corresponding specloop, so that delta calculation is not skipped
987 later in set_delta. */
988 loop->specloop[n] = NULL;
990 /* We are constructing the temporary's descriptor based on the loop
991 dimensions. As the dimensions may be accessed in arbitrary order
992 (think of transpose) the size taken from the n'th loop may not map
993 to the n'th dimension of the array. We need to reconstruct loop infos
994 in the right order before using it to set the descriptor
996 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
997 from[tmp_dim] = loop->from[n];
998 to[tmp_dim] = loop->to[n];
1000 info->delta[dim] = gfc_index_zero_node;
1001 info->start[dim] = gfc_index_zero_node;
1002 info->end[dim] = gfc_index_zero_node;
1003 info->stride[dim] = gfc_index_one_node;
1006 /* Initialize the descriptor. */
1008 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1009 GFC_ARRAY_UNKNOWN, true);
1010 desc = gfc_create_var (type, "atmp");
1011 GFC_DECL_PACKED_ARRAY (desc) = 1;
1013 info->descriptor = desc;
1014 size = gfc_index_one_node;
1016 /* Fill in the array dtype. */
1017 tmp = gfc_conv_descriptor_dtype (desc);
1018 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1021 Fill in the bounds and stride. This is a packed array, so:
1024 for (n = 0; n < rank; n++)
1027 delta = ubound[n] + 1 - lbound[n];
1028 size = size * delta;
1030 size = size * sizeof(element);
1033 or_expr = NULL_TREE;
1035 /* If there is at least one null loop->to[n], it is a callee allocated
1037 for (n = 0; n < total_dim; n++)
1038 if (to[n] == NULL_TREE)
1044 if (size == NULL_TREE)
1046 for (n = 0; n < loop->dimen; n++)
1048 dim = get_scalarizer_dim_for_array_dim (ss, ss->dim[n]);
1050 /* For a callee allocated array express the loop bounds in terms
1051 of the descriptor fields. */
1052 tmp = fold_build2_loc (input_location,
1053 MINUS_EXPR, gfc_array_index_type,
1054 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1055 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1061 for (n = 0; n < total_dim; n++)
1063 /* Store the stride and bound components in the descriptor. */
1064 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1066 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1067 gfc_index_zero_node);
1069 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1071 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1072 gfc_array_index_type,
1073 to[n], gfc_index_one_node);
1075 /* Check whether the size for this dimension is negative. */
1076 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1077 tmp, gfc_index_zero_node);
1078 cond = gfc_evaluate_now (cond, pre);
1083 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1084 boolean_type_node, or_expr, cond);
1086 size = fold_build2_loc (input_location, MULT_EXPR,
1087 gfc_array_index_type, size, tmp);
1088 size = gfc_evaluate_now (size, pre);
1092 /* Get the size of the array. */
1093 if (size && !callee_alloc)
1095 /* If or_expr is true, then the extent in at least one
1096 dimension is zero and the size is set to zero. */
1097 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1098 or_expr, gfc_index_zero_node, size);
1101 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1103 fold_convert (gfc_array_index_type,
1104 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
1112 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1115 if (ss->dimen > ss->loop->temp_dim)
1116 ss->loop->temp_dim = ss->dimen;
1122 /* Return the number of iterations in a loop that starts at START,
1123 ends at END, and has step STEP. */
1126 gfc_get_iteration_count (tree start, tree end, tree step)
1131 type = TREE_TYPE (step);
1132 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1133 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1134 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1135 build_int_cst (type, 1));
1136 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1137 build_int_cst (type, 0));
1138 return fold_convert (gfc_array_index_type, tmp);
1142 /* Extend the data in array DESC by EXTRA elements. */
1145 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1152 if (integer_zerop (extra))
1155 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1157 /* Add EXTRA to the upper bound. */
1158 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1160 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1162 /* Get the value of the current data pointer. */
1163 arg0 = gfc_conv_descriptor_data_get (desc);
1165 /* Calculate the new array size. */
1166 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1167 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1168 ubound, gfc_index_one_node);
1169 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1170 fold_convert (size_type_node, tmp),
1171 fold_convert (size_type_node, size));
1173 /* Call the realloc() function. */
1174 tmp = gfc_call_realloc (pblock, arg0, arg1);
1175 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1179 /* Return true if the bounds of iterator I can only be determined
1183 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1185 return (i->start->expr_type != EXPR_CONSTANT
1186 || i->end->expr_type != EXPR_CONSTANT
1187 || i->step->expr_type != EXPR_CONSTANT);
1191 /* Split the size of constructor element EXPR into the sum of two terms,
1192 one of which can be determined at compile time and one of which must
1193 be calculated at run time. Set *SIZE to the former and return true
1194 if the latter might be nonzero. */
1197 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1199 if (expr->expr_type == EXPR_ARRAY)
1200 return gfc_get_array_constructor_size (size, expr->value.constructor);
1201 else if (expr->rank > 0)
1203 /* Calculate everything at run time. */
1204 mpz_set_ui (*size, 0);
1209 /* A single element. */
1210 mpz_set_ui (*size, 1);
1216 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1217 of array constructor C. */
1220 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1228 mpz_set_ui (*size, 0);
1233 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1236 if (i && gfc_iterator_has_dynamic_bounds (i))
1240 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1243 /* Multiply the static part of the element size by the
1244 number of iterations. */
1245 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1246 mpz_fdiv_q (val, val, i->step->value.integer);
1247 mpz_add_ui (val, val, 1);
1248 if (mpz_sgn (val) > 0)
1249 mpz_mul (len, len, val);
1251 mpz_set_ui (len, 0);
1253 mpz_add (*size, *size, len);
1262 /* Make sure offset is a variable. */
1265 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1268 /* We should have already created the offset variable. We cannot
1269 create it here because we may be in an inner scope. */
1270 gcc_assert (*offsetvar != NULL_TREE);
1271 gfc_add_modify (pblock, *offsetvar, *poffset);
1272 *poffset = *offsetvar;
1273 TREE_USED (*offsetvar) = 1;
1277 /* Variables needed for bounds-checking. */
1278 static bool first_len;
1279 static tree first_len_val;
1280 static bool typespec_chararray_ctor;
1283 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1284 tree offset, gfc_se * se, gfc_expr * expr)
1288 gfc_conv_expr (se, expr);
1290 /* Store the value. */
1291 tmp = build_fold_indirect_ref_loc (input_location,
1292 gfc_conv_descriptor_data_get (desc));
1293 tmp = gfc_build_array_ref (tmp, offset, NULL);
1295 if (expr->ts.type == BT_CHARACTER)
1297 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1300 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1301 esize = fold_convert (gfc_charlen_type_node, esize);
1302 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1303 gfc_charlen_type_node, esize,
1304 build_int_cst (gfc_charlen_type_node,
1305 gfc_character_kinds[i].bit_size / 8));
1307 gfc_conv_string_parameter (se);
1308 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1310 /* The temporary is an array of pointers. */
1311 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1312 gfc_add_modify (&se->pre, tmp, se->expr);
1316 /* The temporary is an array of string values. */
1317 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1318 /* We know the temporary and the value will be the same length,
1319 so can use memcpy. */
1320 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1321 se->string_length, se->expr, expr->ts.kind);
1323 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1327 gfc_add_modify (&se->pre, first_len_val,
1333 /* Verify that all constructor elements are of the same
1335 tree cond = fold_build2_loc (input_location, NE_EXPR,
1336 boolean_type_node, first_len_val,
1338 gfc_trans_runtime_check
1339 (true, false, cond, &se->pre, &expr->where,
1340 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1341 fold_convert (long_integer_type_node, first_len_val),
1342 fold_convert (long_integer_type_node, se->string_length));
1348 /* TODO: Should the frontend already have done this conversion? */
1349 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1350 gfc_add_modify (&se->pre, tmp, se->expr);
1353 gfc_add_block_to_block (pblock, &se->pre);
1354 gfc_add_block_to_block (pblock, &se->post);
1358 /* Add the contents of an array to the constructor. DYNAMIC is as for
1359 gfc_trans_array_constructor_value. */
1362 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1363 tree type ATTRIBUTE_UNUSED,
1364 tree desc, gfc_expr * expr,
1365 tree * poffset, tree * offsetvar,
1376 /* We need this to be a variable so we can increment it. */
1377 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1379 gfc_init_se (&se, NULL);
1381 /* Walk the array expression. */
1382 ss = gfc_walk_expr (expr);
1383 gcc_assert (ss != gfc_ss_terminator);
1385 /* Initialize the scalarizer. */
1386 gfc_init_loopinfo (&loop);
1387 gfc_add_ss_to_loop (&loop, ss);
1389 /* Initialize the loop. */
1390 gfc_conv_ss_startstride (&loop);
1391 gfc_conv_loop_setup (&loop, &expr->where);
1393 /* Make sure the constructed array has room for the new data. */
1396 /* Set SIZE to the total number of elements in the subarray. */
1397 size = gfc_index_one_node;
1398 for (n = 0; n < loop.dimen; n++)
1400 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1401 gfc_index_one_node);
1402 size = fold_build2_loc (input_location, MULT_EXPR,
1403 gfc_array_index_type, size, tmp);
1406 /* Grow the constructed array by SIZE elements. */
1407 gfc_grow_array (&loop.pre, desc, size);
1410 /* Make the loop body. */
1411 gfc_mark_ss_chain_used (ss, 1);
1412 gfc_start_scalarized_body (&loop, &body);
1413 gfc_copy_loopinfo_to_se (&se, &loop);
1416 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1417 gcc_assert (se.ss == gfc_ss_terminator);
1419 /* Increment the offset. */
1420 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1421 *poffset, gfc_index_one_node);
1422 gfc_add_modify (&body, *poffset, tmp);
1424 /* Finish the loop. */
1425 gfc_trans_scalarizing_loops (&loop, &body);
1426 gfc_add_block_to_block (&loop.pre, &loop.post);
1427 tmp = gfc_finish_block (&loop.pre);
1428 gfc_add_expr_to_block (pblock, tmp);
1430 gfc_cleanup_loop (&loop);
1434 /* Assign the values to the elements of an array constructor. DYNAMIC
1435 is true if descriptor DESC only contains enough data for the static
1436 size calculated by gfc_get_array_constructor_size. When true, memory
1437 for the dynamic parts must be allocated using realloc. */
1440 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1441 tree desc, gfc_constructor_base base,
1442 tree * poffset, tree * offsetvar,
1451 tree shadow_loopvar = NULL_TREE;
1452 gfc_saved_var saved_loopvar;
1455 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1457 /* If this is an iterator or an array, the offset must be a variable. */
1458 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1459 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1461 /* Shadowing the iterator avoids changing its value and saves us from
1462 keeping track of it. Further, it makes sure that there's always a
1463 backend-decl for the symbol, even if there wasn't one before,
1464 e.g. in the case of an iterator that appears in a specification
1465 expression in an interface mapping. */
1468 gfc_symbol *sym = c->iterator->var->symtree->n.sym;
1469 tree type = gfc_typenode_for_spec (&sym->ts);
1471 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1472 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1475 gfc_start_block (&body);
1477 if (c->expr->expr_type == EXPR_ARRAY)
1479 /* Array constructors can be nested. */
1480 gfc_trans_array_constructor_value (&body, type, desc,
1481 c->expr->value.constructor,
1482 poffset, offsetvar, dynamic);
1484 else if (c->expr->rank > 0)
1486 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1487 poffset, offsetvar, dynamic);
1491 /* This code really upsets the gimplifier so don't bother for now. */
1498 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1500 p = gfc_constructor_next (p);
1505 /* Scalar values. */
1506 gfc_init_se (&se, NULL);
1507 gfc_trans_array_ctor_element (&body, desc, *poffset,
1510 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1511 gfc_array_index_type,
1512 *poffset, gfc_index_one_node);
1516 /* Collect multiple scalar constants into a constructor. */
1517 VEC(constructor_elt,gc) *v = NULL;
1521 HOST_WIDE_INT idx = 0;
1524 /* Count the number of consecutive scalar constants. */
1525 while (p && !(p->iterator
1526 || p->expr->expr_type != EXPR_CONSTANT))
1528 gfc_init_se (&se, NULL);
1529 gfc_conv_constant (&se, p->expr);
1531 if (c->expr->ts.type != BT_CHARACTER)
1532 se.expr = fold_convert (type, se.expr);
1533 /* For constant character array constructors we build
1534 an array of pointers. */
1535 else if (POINTER_TYPE_P (type))
1536 se.expr = gfc_build_addr_expr
1537 (gfc_get_pchar_type (p->expr->ts.kind),
1540 CONSTRUCTOR_APPEND_ELT (v,
1541 build_int_cst (gfc_array_index_type,
1545 p = gfc_constructor_next (p);
1548 bound = size_int (n - 1);
1549 /* Create an array type to hold them. */
1550 tmptype = build_range_type (gfc_array_index_type,
1551 gfc_index_zero_node, bound);
1552 tmptype = build_array_type (type, tmptype);
1554 init = build_constructor (tmptype, v);
1555 TREE_CONSTANT (init) = 1;
1556 TREE_STATIC (init) = 1;
1557 /* Create a static variable to hold the data. */
1558 tmp = gfc_create_var (tmptype, "data");
1559 TREE_STATIC (tmp) = 1;
1560 TREE_CONSTANT (tmp) = 1;
1561 TREE_READONLY (tmp) = 1;
1562 DECL_INITIAL (tmp) = init;
1565 /* Use BUILTIN_MEMCPY to assign the values. */
1566 tmp = gfc_conv_descriptor_data_get (desc);
1567 tmp = build_fold_indirect_ref_loc (input_location,
1569 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1570 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1571 init = gfc_build_addr_expr (NULL_TREE, init);
1573 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1574 bound = build_int_cst (size_type_node, n * size);
1575 tmp = build_call_expr_loc (input_location,
1576 builtin_decl_explicit (BUILT_IN_MEMCPY),
1577 3, tmp, init, bound);
1578 gfc_add_expr_to_block (&body, tmp);
1580 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1581 gfc_array_index_type, *poffset,
1582 build_int_cst (gfc_array_index_type, n));
1584 if (!INTEGER_CST_P (*poffset))
1586 gfc_add_modify (&body, *offsetvar, *poffset);
1587 *poffset = *offsetvar;
1591 /* The frontend should already have done any expansions
1595 /* Pass the code as is. */
1596 tmp = gfc_finish_block (&body);
1597 gfc_add_expr_to_block (pblock, tmp);
1601 /* Build the implied do-loop. */
1602 stmtblock_t implied_do_block;
1610 loopbody = gfc_finish_block (&body);
1612 /* Create a new block that holds the implied-do loop. A temporary
1613 loop-variable is used. */
1614 gfc_start_block(&implied_do_block);
1616 /* Initialize the loop. */
1617 gfc_init_se (&se, NULL);
1618 gfc_conv_expr_val (&se, c->iterator->start);
1619 gfc_add_block_to_block (&implied_do_block, &se.pre);
1620 gfc_add_modify (&implied_do_block, shadow_loopvar, se.expr);
1622 gfc_init_se (&se, NULL);
1623 gfc_conv_expr_val (&se, c->iterator->end);
1624 gfc_add_block_to_block (&implied_do_block, &se.pre);
1625 end = gfc_evaluate_now (se.expr, &implied_do_block);
1627 gfc_init_se (&se, NULL);
1628 gfc_conv_expr_val (&se, c->iterator->step);
1629 gfc_add_block_to_block (&implied_do_block, &se.pre);
1630 step = gfc_evaluate_now (se.expr, &implied_do_block);
1632 /* If this array expands dynamically, and the number of iterations
1633 is not constant, we won't have allocated space for the static
1634 part of C->EXPR's size. Do that now. */
1635 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1637 /* Get the number of iterations. */
1638 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1640 /* Get the static part of C->EXPR's size. */
1641 gfc_get_array_constructor_element_size (&size, c->expr);
1642 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1644 /* Grow the array by TMP * TMP2 elements. */
1645 tmp = fold_build2_loc (input_location, MULT_EXPR,
1646 gfc_array_index_type, tmp, tmp2);
1647 gfc_grow_array (&implied_do_block, desc, tmp);
1650 /* Generate the loop body. */
1651 exit_label = gfc_build_label_decl (NULL_TREE);
1652 gfc_start_block (&body);
1654 /* Generate the exit condition. Depending on the sign of
1655 the step variable we have to generate the correct
1657 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1658 step, build_int_cst (TREE_TYPE (step), 0));
1659 cond = fold_build3_loc (input_location, COND_EXPR,
1660 boolean_type_node, tmp,
1661 fold_build2_loc (input_location, GT_EXPR,
1662 boolean_type_node, shadow_loopvar, end),
1663 fold_build2_loc (input_location, LT_EXPR,
1664 boolean_type_node, shadow_loopvar, end));
1665 tmp = build1_v (GOTO_EXPR, exit_label);
1666 TREE_USED (exit_label) = 1;
1667 tmp = build3_v (COND_EXPR, cond, tmp,
1668 build_empty_stmt (input_location));
1669 gfc_add_expr_to_block (&body, tmp);
1671 /* The main loop body. */
1672 gfc_add_expr_to_block (&body, loopbody);
1674 /* Increase loop variable by step. */
1675 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1676 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1678 gfc_add_modify (&body, shadow_loopvar, tmp);
1680 /* Finish the loop. */
1681 tmp = gfc_finish_block (&body);
1682 tmp = build1_v (LOOP_EXPR, tmp);
1683 gfc_add_expr_to_block (&implied_do_block, tmp);
1685 /* Add the exit label. */
1686 tmp = build1_v (LABEL_EXPR, exit_label);
1687 gfc_add_expr_to_block (&implied_do_block, tmp);
1689 /* Finishe the implied-do loop. */
1690 tmp = gfc_finish_block(&implied_do_block);
1691 gfc_add_expr_to_block(pblock, tmp);
1693 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1700 /* A catch-all to obtain the string length for anything that is not a
1701 a substring of non-constant length, a constant, array or variable. */
1704 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1709 /* Don't bother if we already know the length is a constant. */
1710 if (*len && INTEGER_CST_P (*len))
1713 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1714 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1717 gfc_conv_const_charlen (e->ts.u.cl);
1718 *len = e->ts.u.cl->backend_decl;
1722 /* Otherwise, be brutal even if inefficient. */
1723 ss = gfc_walk_expr (e);
1724 gfc_init_se (&se, NULL);
1726 /* No function call, in case of side effects. */
1727 se.no_function_call = 1;
1728 if (ss == gfc_ss_terminator)
1729 gfc_conv_expr (&se, e);
1731 gfc_conv_expr_descriptor (&se, e, ss);
1733 /* Fix the value. */
1734 *len = gfc_evaluate_now (se.string_length, &se.pre);
1736 gfc_add_block_to_block (block, &se.pre);
1737 gfc_add_block_to_block (block, &se.post);
1739 e->ts.u.cl->backend_decl = *len;
1744 /* Figure out the string length of a variable reference expression.
1745 Used by get_array_ctor_strlen. */
1748 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
1754 /* Don't bother if we already know the length is a constant. */
1755 if (*len && INTEGER_CST_P (*len))
1758 ts = &expr->symtree->n.sym->ts;
1759 for (ref = expr->ref; ref; ref = ref->next)
1764 /* Array references don't change the string length. */
1768 /* Use the length of the component. */
1769 ts = &ref->u.c.component->ts;
1773 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1774 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1776 /* Note that this might evaluate expr. */
1777 get_array_ctor_all_strlen (block, expr, len);
1780 mpz_init_set_ui (char_len, 1);
1781 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1782 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1783 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1784 *len = convert (gfc_charlen_type_node, *len);
1785 mpz_clear (char_len);
1793 *len = ts->u.cl->backend_decl;
1797 /* Figure out the string length of a character array constructor.
1798 If len is NULL, don't calculate the length; this happens for recursive calls
1799 when a sub-array-constructor is an element but not at the first position,
1800 so when we're not interested in the length.
1801 Returns TRUE if all elements are character constants. */
1804 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
1811 if (gfc_constructor_first (base) == NULL)
1814 *len = build_int_cstu (gfc_charlen_type_node, 0);
1818 /* Loop over all constructor elements to find out is_const, but in len we
1819 want to store the length of the first, not the last, element. We can
1820 of course exit the loop as soon as is_const is found to be false. */
1821 for (c = gfc_constructor_first (base);
1822 c && is_const; c = gfc_constructor_next (c))
1824 switch (c->expr->expr_type)
1827 if (len && !(*len && INTEGER_CST_P (*len)))
1828 *len = build_int_cstu (gfc_charlen_type_node,
1829 c->expr->value.character.length);
1833 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1840 get_array_ctor_var_strlen (block, c->expr, len);
1846 get_array_ctor_all_strlen (block, c->expr, len);
1850 /* After the first iteration, we don't want the length modified. */
1857 /* Check whether the array constructor C consists entirely of constant
1858 elements, and if so returns the number of those elements, otherwise
1859 return zero. Note, an empty or NULL array constructor returns zero. */
1861 unsigned HOST_WIDE_INT
1862 gfc_constant_array_constructor_p (gfc_constructor_base base)
1864 unsigned HOST_WIDE_INT nelem = 0;
1866 gfc_constructor *c = gfc_constructor_first (base);
1870 || c->expr->rank > 0
1871 || c->expr->expr_type != EXPR_CONSTANT)
1873 c = gfc_constructor_next (c);
1880 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1881 and the tree type of it's elements, TYPE, return a static constant
1882 variable that is compile-time initialized. */
1885 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1887 tree tmptype, init, tmp;
1888 HOST_WIDE_INT nelem;
1893 VEC(constructor_elt,gc) *v = NULL;
1895 /* First traverse the constructor list, converting the constants
1896 to tree to build an initializer. */
1898 c = gfc_constructor_first (expr->value.constructor);
1901 gfc_init_se (&se, NULL);
1902 gfc_conv_constant (&se, c->expr);
1903 if (c->expr->ts.type != BT_CHARACTER)
1904 se.expr = fold_convert (type, se.expr);
1905 else if (POINTER_TYPE_P (type))
1906 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
1908 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
1910 c = gfc_constructor_next (c);
1914 /* Next determine the tree type for the array. We use the gfortran
1915 front-end's gfc_get_nodesc_array_type in order to create a suitable
1916 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1918 memset (&as, 0, sizeof (gfc_array_spec));
1920 as.rank = expr->rank;
1921 as.type = AS_EXPLICIT;
1924 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1925 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
1929 for (i = 0; i < expr->rank; i++)
1931 int tmp = (int) mpz_get_si (expr->shape[i]);
1932 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1933 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
1937 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
1939 /* as is not needed anymore. */
1940 for (i = 0; i < as.rank + as.corank; i++)
1942 gfc_free_expr (as.lower[i]);
1943 gfc_free_expr (as.upper[i]);
1946 init = build_constructor (tmptype, v);
1948 TREE_CONSTANT (init) = 1;
1949 TREE_STATIC (init) = 1;
1951 tmp = gfc_create_var (tmptype, "A");
1952 TREE_STATIC (tmp) = 1;
1953 TREE_CONSTANT (tmp) = 1;
1954 TREE_READONLY (tmp) = 1;
1955 DECL_INITIAL (tmp) = init;
1961 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1962 This mostly initializes the scalarizer state info structure with the
1963 appropriate values to directly use the array created by the function
1964 gfc_build_constant_array_constructor. */
1967 trans_constant_array_constructor (gfc_ss * ss, tree type)
1969 gfc_array_info *info;
1973 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
1975 info = &ss->info->data.array;
1977 info->descriptor = tmp;
1978 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
1979 info->offset = gfc_index_zero_node;
1981 for (i = 0; i < ss->dimen; i++)
1983 info->delta[i] = gfc_index_zero_node;
1984 info->start[i] = gfc_index_zero_node;
1985 info->end[i] = gfc_index_zero_node;
1986 info->stride[i] = gfc_index_one_node;
1991 /* Helper routine of gfc_trans_array_constructor to determine if the
1992 bounds of the loop specified by LOOP are constant and simple enough
1993 to use with trans_constant_array_constructor. Returns the
1994 iteration count of the loop if suitable, and NULL_TREE otherwise. */
1997 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1999 tree size = gfc_index_one_node;
2003 for (i = 0; i < loop->dimen; i++)
2005 /* If the bounds aren't constant, return NULL_TREE. */
2006 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2008 if (!integer_zerop (loop->from[i]))
2010 /* Only allow nonzero "from" in one-dimensional arrays. */
2011 if (loop->dimen != 1)
2013 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2014 gfc_array_index_type,
2015 loop->to[i], loop->from[i]);
2019 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2020 tmp, gfc_index_one_node);
2021 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2029 /* Array constructors are handled by constructing a temporary, then using that
2030 within the scalarization loop. This is not optimal, but seems by far the
2034 trans_array_constructor (gfc_ss * ss, locus * where)
2036 gfc_constructor_base c;
2043 bool old_first_len, old_typespec_chararray_ctor;
2044 tree old_first_len_val;
2046 gfc_ss_info *ss_info;
2050 /* Save the old values for nested checking. */
2051 old_first_len = first_len;
2052 old_first_len_val = first_len_val;
2053 old_typespec_chararray_ctor = typespec_chararray_ctor;
2057 expr = ss_info->expr;
2059 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2060 typespec was given for the array constructor. */
2061 typespec_chararray_ctor = (expr->ts.u.cl
2062 && expr->ts.u.cl->length_from_typespec);
2064 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2065 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2067 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2071 gcc_assert (ss->dimen == loop->dimen);
2073 c = expr->value.constructor;
2074 if (expr->ts.type == BT_CHARACTER)
2078 /* get_array_ctor_strlen walks the elements of the constructor, if a
2079 typespec was given, we already know the string length and want the one
2081 if (typespec_chararray_ctor && expr->ts.u.cl->length
2082 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2086 const_string = false;
2087 gfc_init_se (&length_se, NULL);
2088 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2089 gfc_charlen_type_node);
2090 ss_info->string_length = length_se.expr;
2091 gfc_add_block_to_block (&loop->pre, &length_se.pre);
2092 gfc_add_block_to_block (&loop->post, &length_se.post);
2095 const_string = get_array_ctor_strlen (&loop->pre, c,
2096 &ss_info->string_length);
2098 /* Complex character array constructors should have been taken care of
2099 and not end up here. */
2100 gcc_assert (ss_info->string_length);
2102 expr->ts.u.cl->backend_decl = ss_info->string_length;
2104 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2106 type = build_pointer_type (type);
2109 type = gfc_typenode_for_spec (&expr->ts);
2111 /* See if the constructor determines the loop bounds. */
2114 if (expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
2116 /* We have a multidimensional parameter. */
2117 for (s = ss; s; s = s->parent)
2120 for (n = 0; n < s->loop->dimen; n++)
2122 s->loop->from[n] = gfc_index_zero_node;
2123 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2124 gfc_index_integer_kind);
2125 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2126 gfc_array_index_type,
2128 gfc_index_one_node);
2133 if (loop->to[0] == NULL_TREE)
2137 /* We should have a 1-dimensional, zero-based loop. */
2138 gcc_assert (loop->dimen == 1);
2139 gcc_assert (integer_zerop (loop->from[0]));
2141 /* Split the constructor size into a static part and a dynamic part.
2142 Allocate the static size up-front and record whether the dynamic
2143 size might be nonzero. */
2145 dynamic = gfc_get_array_constructor_size (&size, c);
2146 mpz_sub_ui (size, size, 1);
2147 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2151 /* Special case constant array constructors. */
2154 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2157 tree size = constant_array_constructor_loop_size (loop);
2158 if (size && compare_tree_int (size, nelem) == 0)
2160 trans_constant_array_constructor (ss, type);
2166 if (TREE_CODE (loop->to[0]) == VAR_DECL)
2169 gfc_trans_create_temp_array (&loop->pre, &loop->post, ss, type, NULL_TREE,
2170 dynamic, true, false, where);
2172 desc = ss_info->data.array.descriptor;
2173 offset = gfc_index_zero_node;
2174 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2175 TREE_NO_WARNING (offsetvar) = 1;
2176 TREE_USED (offsetvar) = 0;
2177 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
2178 &offset, &offsetvar, dynamic);
2180 /* If the array grows dynamically, the upper bound of the loop variable
2181 is determined by the array's final upper bound. */
2184 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2185 gfc_array_index_type,
2186 offsetvar, gfc_index_one_node);
2187 tmp = gfc_evaluate_now (tmp, &loop->pre);
2188 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2189 if (loop->to[0] && TREE_CODE (loop->to[0]) == VAR_DECL)
2190 gfc_add_modify (&loop->pre, loop->to[0], tmp);
2195 if (TREE_USED (offsetvar))
2196 pushdecl (offsetvar);
2198 gcc_assert (INTEGER_CST_P (offset));
2201 /* Disable bound checking for now because it's probably broken. */
2202 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2209 /* Restore old values of globals. */
2210 first_len = old_first_len;
2211 first_len_val = old_first_len_val;
2212 typespec_chararray_ctor = old_typespec_chararray_ctor;
2216 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2217 called after evaluating all of INFO's vector dimensions. Go through
2218 each such vector dimension and see if we can now fill in any missing
2222 set_vector_loop_bounds (gfc_ss * ss)
2225 gfc_array_info *info;
2233 info = &ss->info->data.array;
2235 for (; ss; ss = ss->parent)
2239 for (n = 0; n < loop->dimen; n++)
2242 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2243 || loop->to[n] != NULL)
2246 /* Loop variable N indexes vector dimension DIM, and we don't
2247 yet know the upper bound of loop variable N. Set it to the
2248 difference between the vector's upper and lower bounds. */
2249 gcc_assert (loop->from[n] == gfc_index_zero_node);
2250 gcc_assert (info->subscript[dim]
2251 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2253 gfc_init_se (&se, NULL);
2254 desc = info->subscript[dim]->info->data.array.descriptor;
2255 zero = gfc_rank_cst[0];
2256 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2257 gfc_array_index_type,
2258 gfc_conv_descriptor_ubound_get (desc, zero),
2259 gfc_conv_descriptor_lbound_get (desc, zero));
2260 tmp = gfc_evaluate_now (tmp, &loop->pre);
2267 /* Add the pre and post chains for all the scalar expressions in a SS chain
2268 to loop. This is called after the loop parameters have been calculated,
2269 but before the actual scalarizing loops. */
2272 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2276 gfc_ss_info *ss_info;
2277 gfc_array_info *info;
2281 /* TODO: This can generate bad code if there are ordering dependencies,
2282 e.g., a callee allocated function and an unknown size constructor. */
2283 gcc_assert (ss != NULL);
2285 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2290 expr = ss_info->expr;
2291 info = &ss_info->data.array;
2293 switch (ss_info->type)
2296 /* Scalar expression. Evaluate this now. This includes elemental
2297 dimension indices, but not array section bounds. */
2298 gfc_init_se (&se, NULL);
2299 gfc_conv_expr (&se, expr);
2300 gfc_add_block_to_block (&loop->pre, &se.pre);
2302 if (expr->ts.type != BT_CHARACTER)
2304 /* Move the evaluation of scalar expressions outside the
2305 scalarization loop, except for WHERE assignments. */
2307 se.expr = convert(gfc_array_index_type, se.expr);
2308 if (!ss_info->where)
2309 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
2310 gfc_add_block_to_block (&loop->pre, &se.post);
2313 gfc_add_block_to_block (&loop->post, &se.post);
2315 ss_info->data.scalar.value = se.expr;
2316 ss_info->string_length = se.string_length;
2319 case GFC_SS_REFERENCE:
2320 /* Scalar argument to elemental procedure. Evaluate this
2322 gfc_init_se (&se, NULL);
2323 gfc_conv_expr (&se, expr);
2324 gfc_add_block_to_block (&loop->pre, &se.pre);
2325 gfc_add_block_to_block (&loop->post, &se.post);
2327 ss_info->data.scalar.value = gfc_evaluate_now (se.expr, &loop->pre);
2328 ss_info->string_length = se.string_length;
2331 case GFC_SS_SECTION:
2332 /* Add the expressions for scalar and vector subscripts. */
2333 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2334 if (info->subscript[n])
2335 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2337 set_vector_loop_bounds (ss);
2341 /* Get the vector's descriptor and store it in SS. */
2342 gfc_init_se (&se, NULL);
2343 gfc_conv_expr_descriptor (&se, expr, gfc_walk_expr (expr));
2344 gfc_add_block_to_block (&loop->pre, &se.pre);
2345 gfc_add_block_to_block (&loop->post, &se.post);
2346 info->descriptor = se.expr;
2349 case GFC_SS_INTRINSIC:
2350 gfc_add_intrinsic_ss_code (loop, ss);
2353 case GFC_SS_FUNCTION:
2354 /* Array function return value. We call the function and save its
2355 result in a temporary for use inside the loop. */
2356 gfc_init_se (&se, NULL);
2359 gfc_conv_expr (&se, expr);
2360 gfc_add_block_to_block (&loop->pre, &se.pre);
2361 gfc_add_block_to_block (&loop->post, &se.post);
2362 ss_info->string_length = se.string_length;
2365 case GFC_SS_CONSTRUCTOR:
2366 if (expr->ts.type == BT_CHARACTER
2367 && ss_info->string_length == NULL
2369 && expr->ts.u.cl->length)
2371 gfc_init_se (&se, NULL);
2372 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2373 gfc_charlen_type_node);
2374 ss_info->string_length = se.expr;
2375 gfc_add_block_to_block (&loop->pre, &se.pre);
2376 gfc_add_block_to_block (&loop->post, &se.post);
2378 trans_array_constructor (ss, where);
2382 case GFC_SS_COMPONENT:
2383 /* Do nothing. These are handled elsewhere. */
2393 /* Translate expressions for the descriptor and data pointer of a SS. */
2397 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2400 gfc_ss_info *ss_info;
2401 gfc_array_info *info;
2405 info = &ss_info->data.array;
2407 /* Get the descriptor for the array to be scalarized. */
2408 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2409 gfc_init_se (&se, NULL);
2410 se.descriptor_only = 1;
2411 gfc_conv_expr_lhs (&se, ss_info->expr);
2412 gfc_add_block_to_block (block, &se.pre);
2413 info->descriptor = se.expr;
2414 ss_info->string_length = se.string_length;
2418 /* Also the data pointer. */
2419 tmp = gfc_conv_array_data (se.expr);
2420 /* If this is a variable or address of a variable we use it directly.
2421 Otherwise we must evaluate it now to avoid breaking dependency
2422 analysis by pulling the expressions for elemental array indices
2425 || (TREE_CODE (tmp) == ADDR_EXPR
2426 && DECL_P (TREE_OPERAND (tmp, 0)))))
2427 tmp = gfc_evaluate_now (tmp, block);
2430 tmp = gfc_conv_array_offset (se.expr);
2431 info->offset = gfc_evaluate_now (tmp, block);
2433 /* Make absolutely sure that the saved_offset is indeed saved
2434 so that the variable is still accessible after the loops
2436 info->saved_offset = info->offset;
2441 /* Initialize a gfc_loopinfo structure. */
2444 gfc_init_loopinfo (gfc_loopinfo * loop)
2448 memset (loop, 0, sizeof (gfc_loopinfo));
2449 gfc_init_block (&loop->pre);
2450 gfc_init_block (&loop->post);
2452 /* Initially scalarize in order and default to no loop reversal. */
2453 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2456 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2459 loop->ss = gfc_ss_terminator;
2463 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2467 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2473 /* Return an expression for the data pointer of an array. */
2476 gfc_conv_array_data (tree descriptor)
2480 type = TREE_TYPE (descriptor);
2481 if (GFC_ARRAY_TYPE_P (type))
2483 if (TREE_CODE (type) == POINTER_TYPE)
2487 /* Descriptorless arrays. */
2488 return gfc_build_addr_expr (NULL_TREE, descriptor);
2492 return gfc_conv_descriptor_data_get (descriptor);
2496 /* Return an expression for the base offset of an array. */
2499 gfc_conv_array_offset (tree descriptor)
2503 type = TREE_TYPE (descriptor);
2504 if (GFC_ARRAY_TYPE_P (type))
2505 return GFC_TYPE_ARRAY_OFFSET (type);
2507 return gfc_conv_descriptor_offset_get (descriptor);
2511 /* Get an expression for the array stride. */
2514 gfc_conv_array_stride (tree descriptor, int dim)
2519 type = TREE_TYPE (descriptor);
2521 /* For descriptorless arrays use the array size. */
2522 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2523 if (tmp != NULL_TREE)
2526 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2531 /* Like gfc_conv_array_stride, but for the lower bound. */
2534 gfc_conv_array_lbound (tree descriptor, int dim)
2539 type = TREE_TYPE (descriptor);
2541 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2542 if (tmp != NULL_TREE)
2545 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2550 /* Like gfc_conv_array_stride, but for the upper bound. */
2553 gfc_conv_array_ubound (tree descriptor, int dim)
2558 type = TREE_TYPE (descriptor);
2560 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2561 if (tmp != NULL_TREE)
2564 /* This should only ever happen when passing an assumed shape array
2565 as an actual parameter. The value will never be used. */
2566 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2567 return gfc_index_zero_node;
2569 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2574 /* Generate code to perform an array index bound check. */
2577 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
2578 locus * where, bool check_upper)
2581 tree tmp_lo, tmp_up;
2584 const char * name = NULL;
2586 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2589 descriptor = ss->info->data.array.descriptor;
2591 index = gfc_evaluate_now (index, &se->pre);
2593 /* We find a name for the error message. */
2594 name = ss->info->expr->symtree->n.sym->name;
2595 gcc_assert (name != NULL);
2597 if (TREE_CODE (descriptor) == VAR_DECL)
2598 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
2600 /* If upper bound is present, include both bounds in the error message. */
2603 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2604 tmp_up = gfc_conv_array_ubound (descriptor, n);
2607 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2608 "outside of expected range (%%ld:%%ld)", n+1, name);
2610 asprintf (&msg, "Index '%%ld' of dimension %d "
2611 "outside of expected range (%%ld:%%ld)", n+1);
2613 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2615 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2616 fold_convert (long_integer_type_node, index),
2617 fold_convert (long_integer_type_node, tmp_lo),
2618 fold_convert (long_integer_type_node, tmp_up));
2619 fault = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2621 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2622 fold_convert (long_integer_type_node, index),
2623 fold_convert (long_integer_type_node, tmp_lo),
2624 fold_convert (long_integer_type_node, tmp_up));
2629 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2632 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2633 "below lower bound of %%ld", n+1, name);
2635 asprintf (&msg, "Index '%%ld' of dimension %d "
2636 "below lower bound of %%ld", n+1);
2638 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2640 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2641 fold_convert (long_integer_type_node, index),
2642 fold_convert (long_integer_type_node, tmp_lo));
2650 /* Return the offset for an index. Performs bound checking for elemental
2651 dimensions. Single element references are processed separately.
2652 DIM is the array dimension, I is the loop dimension. */
2655 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
2656 gfc_array_ref * ar, tree stride)
2658 gfc_array_info *info;
2663 info = &ss->info->data.array;
2665 /* Get the index into the array for this dimension. */
2668 gcc_assert (ar->type != AR_ELEMENT);
2669 switch (ar->dimen_type[dim])
2671 case DIMEN_THIS_IMAGE:
2675 /* Elemental dimension. */
2676 gcc_assert (info->subscript[dim]
2677 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
2678 /* We've already translated this value outside the loop. */
2679 index = info->subscript[dim]->info->data.scalar.value;
2681 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2682 ar->as->type != AS_ASSUMED_SIZE
2683 || dim < ar->dimen - 1);
2687 gcc_assert (info && se->loop);
2688 gcc_assert (info->subscript[dim]
2689 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2690 desc = info->subscript[dim]->info->data.array.descriptor;
2692 /* Get a zero-based index into the vector. */
2693 index = fold_build2_loc (input_location, MINUS_EXPR,
2694 gfc_array_index_type,
2695 se->loop->loopvar[i], se->loop->from[i]);
2697 /* Multiply the index by the stride. */
2698 index = fold_build2_loc (input_location, MULT_EXPR,
2699 gfc_array_index_type,
2700 index, gfc_conv_array_stride (desc, 0));
2702 /* Read the vector to get an index into info->descriptor. */
2703 data = build_fold_indirect_ref_loc (input_location,
2704 gfc_conv_array_data (desc));
2705 index = gfc_build_array_ref (data, index, NULL);
2706 index = gfc_evaluate_now (index, &se->pre);
2707 index = fold_convert (gfc_array_index_type, index);
2709 /* Do any bounds checking on the final info->descriptor index. */
2710 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2711 ar->as->type != AS_ASSUMED_SIZE
2712 || dim < ar->dimen - 1);
2716 /* Scalarized dimension. */
2717 gcc_assert (info && se->loop);
2719 /* Multiply the loop variable by the stride and delta. */
2720 index = se->loop->loopvar[i];
2721 if (!integer_onep (info->stride[dim]))
2722 index = fold_build2_loc (input_location, MULT_EXPR,
2723 gfc_array_index_type, index,
2725 if (!integer_zerop (info->delta[dim]))
2726 index = fold_build2_loc (input_location, PLUS_EXPR,
2727 gfc_array_index_type, index,
2737 /* Temporary array or derived type component. */
2738 gcc_assert (se->loop);
2739 index = se->loop->loopvar[se->loop->order[i]];
2741 /* Pointer functions can have stride[0] different from unity.
2742 Use the stride returned by the function call and stored in
2743 the descriptor for the temporary. */
2744 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
2745 && se->ss->info->expr
2746 && se->ss->info->expr->symtree
2747 && se->ss->info->expr->symtree->n.sym->result
2748 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
2749 stride = gfc_conv_descriptor_stride_get (info->descriptor,
2752 if (!integer_zerop (info->delta[dim]))
2753 index = fold_build2_loc (input_location, PLUS_EXPR,
2754 gfc_array_index_type, index, info->delta[dim]);
2757 /* Multiply by the stride. */
2758 if (!integer_onep (stride))
2759 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2766 /* Build a scalarized reference to an array. */
2769 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2771 gfc_array_info *info;
2772 tree decl = NULL_TREE;
2780 expr = ss->info->expr;
2781 info = &ss->info->data.array;
2783 n = se->loop->order[0];
2787 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
2788 /* Add the offset for this dimension to the stored offset for all other
2790 if (!integer_zerop (info->offset))
2791 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2792 index, info->offset);
2794 if (expr && is_subref_array (expr))
2795 decl = expr->symtree->n.sym->backend_decl;
2797 tmp = build_fold_indirect_ref_loc (input_location, info->data);
2798 se->expr = gfc_build_array_ref (tmp, index, decl);
2802 /* Translate access of temporary array. */
2805 gfc_conv_tmp_array_ref (gfc_se * se)
2807 se->string_length = se->ss->info->string_length;
2808 gfc_conv_scalarized_array_ref (se, NULL);
2809 gfc_advance_se_ss_chain (se);
2812 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
2815 add_to_offset (tree *cst_offset, tree *offset, tree t)
2817 if (TREE_CODE (t) == INTEGER_CST)
2818 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
2821 if (!integer_zerop (*offset))
2822 *offset = fold_build2_loc (input_location, PLUS_EXPR,
2823 gfc_array_index_type, *offset, t);
2829 /* Build an array reference. se->expr already holds the array descriptor.
2830 This should be either a variable, indirect variable reference or component
2831 reference. For arrays which do not have a descriptor, se->expr will be
2833 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2836 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2840 tree offset, cst_offset;
2848 gcc_assert (ar->codimen);
2850 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
2851 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
2854 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
2855 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
2856 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
2858 /* Use the actual tree type and not the wrapped coarray. */
2859 if (!se->want_pointer)
2860 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
2867 /* Handle scalarized references separately. */
2868 if (ar->type != AR_ELEMENT)
2870 gfc_conv_scalarized_array_ref (se, ar);
2871 gfc_advance_se_ss_chain (se);
2875 cst_offset = offset = gfc_index_zero_node;
2876 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
2878 /* Calculate the offsets from all the dimensions. Make sure to associate
2879 the final offset so that we form a chain of loop invariant summands. */
2880 for (n = ar->dimen - 1; n >= 0; n--)
2882 /* Calculate the index for this dimension. */
2883 gfc_init_se (&indexse, se);
2884 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2885 gfc_add_block_to_block (&se->pre, &indexse.pre);
2887 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2889 /* Check array bounds. */
2893 /* Evaluate the indexse.expr only once. */
2894 indexse.expr = save_expr (indexse.expr);
2897 tmp = gfc_conv_array_lbound (se->expr, n);
2898 if (sym->attr.temporary)
2900 gfc_init_se (&tmpse, se);
2901 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
2902 gfc_array_index_type);
2903 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2907 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2909 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2910 "below lower bound of %%ld", n+1, sym->name);
2911 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2912 fold_convert (long_integer_type_node,
2914 fold_convert (long_integer_type_node, tmp));
2917 /* Upper bound, but not for the last dimension of assumed-size
2919 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
2921 tmp = gfc_conv_array_ubound (se->expr, n);
2922 if (sym->attr.temporary)
2924 gfc_init_se (&tmpse, se);
2925 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
2926 gfc_array_index_type);
2927 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2931 cond = fold_build2_loc (input_location, GT_EXPR,
2932 boolean_type_node, indexse.expr, tmp);
2933 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2934 "above upper bound of %%ld", n+1, sym->name);
2935 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2936 fold_convert (long_integer_type_node,
2938 fold_convert (long_integer_type_node, tmp));
2943 /* Multiply the index by the stride. */
2944 stride = gfc_conv_array_stride (se->expr, n);
2945 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2946 indexse.expr, stride);
2948 /* And add it to the total. */
2949 add_to_offset (&cst_offset, &offset, tmp);
2952 if (!integer_zerop (cst_offset))
2953 offset = fold_build2_loc (input_location, PLUS_EXPR,
2954 gfc_array_index_type, offset, cst_offset);
2956 /* Access the calculated element. */
2957 tmp = gfc_conv_array_data (se->expr);
2958 tmp = build_fold_indirect_ref (tmp);
2959 se->expr = gfc_build_array_ref (tmp, offset, sym->backend_decl);
2963 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
2964 LOOP_DIM dimension (if any) to array's offset. */
2967 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
2968 gfc_array_ref *ar, int array_dim, int loop_dim)
2971 gfc_array_info *info;
2974 info = &ss->info->data.array;
2976 gfc_init_se (&se, NULL);
2978 se.expr = info->descriptor;
2979 stride = gfc_conv_array_stride (info->descriptor, array_dim);
2980 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
2981 gfc_add_block_to_block (pblock, &se.pre);
2983 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
2984 gfc_array_index_type,
2985 info->offset, index);
2986 info->offset = gfc_evaluate_now (info->offset, pblock);
2990 /* Generate the code to be executed immediately before entering a
2991 scalarization loop. */
2994 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2995 stmtblock_t * pblock)
2998 gfc_ss_info *ss_info;
2999 gfc_array_info *info;
3000 gfc_ss_type ss_type;
3005 /* This code will be executed before entering the scalarization loop
3006 for this dimension. */
3007 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3011 if ((ss_info->useflags & flag) == 0)
3014 ss_type = ss_info->type;
3015 if (ss_type != GFC_SS_SECTION
3016 && ss_type != GFC_SS_FUNCTION
3017 && ss_type != GFC_SS_CONSTRUCTOR
3018 && ss_type != GFC_SS_COMPONENT)
3021 info = &ss_info->data.array;
3023 gcc_assert (dim < ss->dimen);
3024 gcc_assert (ss->dimen == loop->dimen);
3027 ar = &info->ref->u.ar;
3031 if (dim == loop->dimen - 1)
3036 /* For the time being, there is no loop reordering. */
3037 gcc_assert (i == loop->order[i]);
3040 if (dim == loop->dimen - 1)
3042 stride = gfc_conv_array_stride (info->descriptor, ss->dim[i]);
3044 /* Calculate the stride of the innermost loop. Hopefully this will
3045 allow the backend optimizers to do their stuff more effectively.
3047 info->stride0 = gfc_evaluate_now (stride, pblock);
3049 /* For the outermost loop calculate the offset due to any
3050 elemental dimensions. It will have been initialized with the
3051 base offset of the array. */
3054 for (i = 0; i < ar->dimen; i++)
3056 if (ar->dimen_type[i] != DIMEN_ELEMENT)
3059 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
3064 /* Add the offset for the previous loop dimension. */
3065 add_array_offset (pblock, loop, ss, ar, ss->dim[i], i);
3067 /* Remember this offset for the second loop. */
3068 if (dim == loop->temp_dim - 1)
3069 info->saved_offset = info->offset;
3074 /* Start a scalarized expression. Creates a scope and declares loop
3078 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
3084 gcc_assert (!loop->array_parameter);
3086 for (dim = loop->dimen - 1; dim >= 0; dim--)
3088 n = loop->order[dim];
3090 gfc_start_block (&loop->code[n]);
3092 /* Create the loop variable. */
3093 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
3095 if (dim < loop->temp_dim)
3099 /* Calculate values that will be constant within this loop. */
3100 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3102 gfc_start_block (pbody);
3106 /* Generates the actual loop code for a scalarization loop. */
3109 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3110 stmtblock_t * pbody)
3121 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
3122 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3123 && n == loop->dimen - 1)
3125 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3126 init = make_tree_vec (1);
3127 cond = make_tree_vec (1);
3128 incr = make_tree_vec (1);
3130 /* Cycle statement is implemented with a goto. Exit statement must not
3131 be present for this loop. */
3132 exit_label = gfc_build_label_decl (NULL_TREE);
3133 TREE_USED (exit_label) = 1;
3135 /* Label for cycle statements (if needed). */
3136 tmp = build1_v (LABEL_EXPR, exit_label);
3137 gfc_add_expr_to_block (pbody, tmp);
3139 stmt = make_node (OMP_FOR);
3141 TREE_TYPE (stmt) = void_type_node;
3142 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3144 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3145 OMP_CLAUSE_SCHEDULE);
3146 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3147 = OMP_CLAUSE_SCHEDULE_STATIC;
3148 if (ompws_flags & OMPWS_NOWAIT)
3149 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3150 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3152 /* Initialize the loopvar. */
3153 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3155 OMP_FOR_INIT (stmt) = init;
3156 /* The exit condition. */
3157 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3159 loop->loopvar[n], loop->to[n]);
3160 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3161 OMP_FOR_COND (stmt) = cond;
3162 /* Increment the loopvar. */
3163 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3164 loop->loopvar[n], gfc_index_one_node);
3165 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3166 void_type_node, loop->loopvar[n], tmp);
3167 OMP_FOR_INCR (stmt) = incr;
3169 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3170 gfc_add_expr_to_block (&loop->code[n], stmt);
3174 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3175 && (loop->temp_ss == NULL);
3177 loopbody = gfc_finish_block (pbody);
3181 tmp = loop->from[n];
3182 loop->from[n] = loop->to[n];
3186 /* Initialize the loopvar. */
3187 if (loop->loopvar[n] != loop->from[n])
3188 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3190 exit_label = gfc_build_label_decl (NULL_TREE);
3192 /* Generate the loop body. */
3193 gfc_init_block (&block);
3195 /* The exit condition. */
3196 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3197 boolean_type_node, loop->loopvar[n], loop->to[n]);
3198 tmp = build1_v (GOTO_EXPR, exit_label);
3199 TREE_USED (exit_label) = 1;
3200 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3201 gfc_add_expr_to_block (&block, tmp);
3203 /* The main body. */
3204 gfc_add_expr_to_block (&block, loopbody);
3206 /* Increment the loopvar. */
3207 tmp = fold_build2_loc (input_location,
3208 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3209 gfc_array_index_type, loop->loopvar[n],
3210 gfc_index_one_node);
3212 gfc_add_modify (&block, loop->loopvar[n], tmp);
3214 /* Build the loop. */
3215 tmp = gfc_finish_block (&block);
3216 tmp = build1_v (LOOP_EXPR, tmp);
3217 gfc_add_expr_to_block (&loop->code[n], tmp);
3219 /* Add the exit label. */
3220 tmp = build1_v (LABEL_EXPR, exit_label);
3221 gfc_add_expr_to_block (&loop->code[n], tmp);
3227 /* Finishes and generates the loops for a scalarized expression. */
3230 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3235 stmtblock_t *pblock;
3239 /* Generate the loops. */
3240 for (dim = 0; dim < loop->dimen; dim++)
3242 n = loop->order[dim];
3243 gfc_trans_scalarized_loop_end (loop, n, pblock);
3244 loop->loopvar[n] = NULL_TREE;
3245 pblock = &loop->code[n];
3248 tmp = gfc_finish_block (pblock);
3249 gfc_add_expr_to_block (&loop->pre, tmp);
3251 /* Clear all the used flags. */
3252 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3253 if (ss->parent == NULL)
3254 ss->info->useflags = 0;
3258 /* Finish the main body of a scalarized expression, and start the secondary
3262 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
3266 stmtblock_t *pblock;
3270 /* We finish as many loops as are used by the temporary. */
3271 for (dim = 0; dim < loop->temp_dim - 1; dim++)
3273 n = loop->order[dim];
3274 gfc_trans_scalarized_loop_end (loop, n, pblock);
3275 loop->loopvar[n] = NULL_TREE;
3276 pblock = &loop->code[n];
3279 /* We don't want to finish the outermost loop entirely. */
3280 n = loop->order[loop->temp_dim - 1];
3281 gfc_trans_scalarized_loop_end (loop, n, pblock);
3283 /* Restore the initial offsets. */
3284 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3286 gfc_ss_type ss_type;
3287 gfc_ss_info *ss_info;
3291 if ((ss_info->useflags & 2) == 0)
3294 ss_type = ss_info->type;
3295 if (ss_type != GFC_SS_SECTION
3296 && ss_type != GFC_SS_FUNCTION
3297 && ss_type != GFC_SS_CONSTRUCTOR
3298 && ss_type != GFC_SS_COMPONENT)
3301 ss_info->data.array.offset = ss_info->data.array.saved_offset;
3304 /* Restart all the inner loops we just finished. */
3305 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
3307 n = loop->order[dim];
3309 gfc_start_block (&loop->code[n]);
3311 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
3313 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
3316 /* Start a block for the secondary copying code. */
3317 gfc_start_block (body);
3321 /* Precalculate (either lower or upper) bound of an array section.
3322 BLOCK: Block in which the (pre)calculation code will go.
3323 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
3324 VALUES[DIM]: Specified bound (NULL <=> unspecified).
3325 DESC: Array descriptor from which the bound will be picked if unspecified
3326 (either lower or upper bound according to LBOUND). */
3329 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
3330 tree desc, int dim, bool lbound)
3333 gfc_expr * input_val = values[dim];
3334 tree *output = &bounds[dim];
3339 /* Specified section bound. */
3340 gfc_init_se (&se, NULL);
3341 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
3342 gfc_add_block_to_block (block, &se.pre);
3347 /* No specific bound specified so use the bound of the array. */
3348 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
3349 gfc_conv_array_ubound (desc, dim);
3351 *output = gfc_evaluate_now (*output, block);
3355 /* Calculate the lower bound of an array section. */
3358 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
3360 gfc_expr *stride = NULL;
3363 gfc_array_info *info;
3366 gcc_assert (ss->info->type == GFC_SS_SECTION);
3368 info = &ss->info->data.array;
3369 ar = &info->ref->u.ar;
3371 if (ar->dimen_type[dim] == DIMEN_VECTOR)
3373 /* We use a zero-based index to access the vector. */
3374 info->start[dim] = gfc_index_zero_node;
3375 info->end[dim] = NULL;
3376 info->stride[dim] = gfc_index_one_node;
3380 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
3381 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
3382 desc = info->descriptor;
3383 stride = ar->stride[dim];
3385 /* Calculate the start of the range. For vector subscripts this will
3386 be the range of the vector. */
3387 evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true);
3389 /* Similarly calculate the end. Although this is not used in the
3390 scalarizer, it is needed when checking bounds and where the end
3391 is an expression with side-effects. */
3392 evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false);
3394 /* Calculate the stride. */
3396 info->stride[dim] = gfc_index_one_node;
3399 gfc_init_se (&se, NULL);
3400 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3401 gfc_add_block_to_block (&loop->pre, &se.pre);
3402 info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre);
3407 /* Calculates the range start and stride for a SS chain. Also gets the
3408 descriptor and data pointer. The range of vector subscripts is the size
3409 of the vector. Array bounds are also checked. */
3412 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3420 /* Determine the rank of the loop. */
3421 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3423 switch (ss->info->type)
3425 case GFC_SS_SECTION:
3426 case GFC_SS_CONSTRUCTOR:
3427 case GFC_SS_FUNCTION:
3428 case GFC_SS_COMPONENT:
3429 loop->dimen = ss->dimen;