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)
499 gfc_free_ss (gfc_ss * ss)
501 gfc_ss_info *ss_info;
506 switch (ss_info->type)
509 for (n = 0; n < ss->dimen; n++)
511 if (ss_info->data.array.subscript[ss->dim[n]])
512 gfc_free_ss_chain (ss_info->data.array.subscript[ss->dim[n]]);
520 free_ss_info (ss_info);
525 /* Creates and initializes an array type gfc_ss struct. */
528 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
531 gfc_ss_info *ss_info;
534 ss_info = gfc_get_ss_info ();
535 ss_info->type = type;
536 ss_info->expr = expr;
542 for (i = 0; i < ss->dimen; i++)
549 /* Creates and initializes a temporary type gfc_ss struct. */
552 gfc_get_temp_ss (tree type, tree string_length, int dimen)
555 gfc_ss_info *ss_info;
558 ss_info = gfc_get_ss_info ();
559 ss_info->type = GFC_SS_TEMP;
560 ss_info->string_length = string_length;
561 ss_info->data.temp.type = type;
565 ss->next = gfc_ss_terminator;
567 for (i = 0; i < ss->dimen; i++)
574 /* Creates and initializes a scalar type gfc_ss struct. */
577 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
580 gfc_ss_info *ss_info;
582 ss_info = gfc_get_ss_info ();
583 ss_info->type = GFC_SS_SCALAR;
584 ss_info->expr = expr;
594 /* Free all the SS associated with a loop. */
597 gfc_cleanup_loop (gfc_loopinfo * loop)
603 while (ss != gfc_ss_terminator)
605 gcc_assert (ss != NULL);
606 next = ss->loop_chain;
613 /* Associate a SS chain with a loop. */
616 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
620 if (head == gfc_ss_terminator)
624 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
626 if (ss->next == gfc_ss_terminator)
627 ss->loop_chain = loop->ss;
629 ss->loop_chain = ss->next;
631 gcc_assert (ss == gfc_ss_terminator);
636 /* Generate an initializer for a static pointer or allocatable array. */
639 gfc_trans_static_array_pointer (gfc_symbol * sym)
643 gcc_assert (TREE_STATIC (sym->backend_decl));
644 /* Just zero the data member. */
645 type = TREE_TYPE (sym->backend_decl);
646 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
650 /* If the bounds of SE's loop have not yet been set, see if they can be
651 determined from array spec AS, which is the array spec of a called
652 function. MAPPING maps the callee's dummy arguments to the values
653 that the caller is passing. Add any initialization and finalization
657 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
658 gfc_se * se, gfc_array_spec * as)
666 if (as && as->type == AS_EXPLICIT)
667 for (n = 0; n < se->loop->dimen; n++)
669 dim = se->ss->dim[n];
670 gcc_assert (dim < as->rank);
671 gcc_assert (se->loop->dimen == as->rank);
672 if (se->loop->to[n] == NULL_TREE)
674 /* Evaluate the lower bound. */
675 gfc_init_se (&tmpse, NULL);
676 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
677 gfc_add_block_to_block (&se->pre, &tmpse.pre);
678 gfc_add_block_to_block (&se->post, &tmpse.post);
679 lower = fold_convert (gfc_array_index_type, tmpse.expr);
681 /* ...and the upper bound. */
682 gfc_init_se (&tmpse, NULL);
683 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
684 gfc_add_block_to_block (&se->pre, &tmpse.pre);
685 gfc_add_block_to_block (&se->post, &tmpse.post);
686 upper = fold_convert (gfc_array_index_type, tmpse.expr);
688 /* Set the upper bound of the loop to UPPER - LOWER. */
689 tmp = fold_build2_loc (input_location, MINUS_EXPR,
690 gfc_array_index_type, upper, lower);
691 tmp = gfc_evaluate_now (tmp, &se->pre);
692 se->loop->to[n] = tmp;
698 /* Generate code to allocate an array temporary, or create a variable to
699 hold the data. If size is NULL, zero the descriptor so that the
700 callee will allocate the array. If DEALLOC is true, also generate code to
701 free the array afterwards.
703 If INITIAL is not NULL, it is packed using internal_pack and the result used
704 as data instead of allocating a fresh, unitialized area of memory.
706 Initialization code is added to PRE and finalization code to POST.
707 DYNAMIC is true if the caller may want to extend the array later
708 using realloc. This prevents us from putting the array on the stack. */
711 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
712 gfc_array_info * info, tree size, tree nelem,
713 tree initial, bool dynamic, bool dealloc)
719 desc = info->descriptor;
720 info->offset = gfc_index_zero_node;
721 if (size == NULL_TREE || integer_zerop (size))
723 /* A callee allocated array. */
724 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
729 /* Allocate the temporary. */
730 onstack = !dynamic && initial == NULL_TREE
731 && (gfc_option.flag_stack_arrays
732 || gfc_can_put_var_on_stack (size));
736 /* Make a temporary variable to hold the data. */
737 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
738 nelem, gfc_index_one_node);
739 tmp = gfc_evaluate_now (tmp, pre);
740 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
742 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
744 tmp = gfc_create_var (tmp, "A");
745 /* If we're here only because of -fstack-arrays we have to
746 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
747 if (!gfc_can_put_var_on_stack (size))
748 gfc_add_expr_to_block (pre,
749 fold_build1_loc (input_location,
750 DECL_EXPR, TREE_TYPE (tmp),
752 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
753 gfc_conv_descriptor_data_set (pre, desc, tmp);
757 /* Allocate memory to hold the data or call internal_pack. */
758 if (initial == NULL_TREE)
760 tmp = gfc_call_malloc (pre, NULL, size);
761 tmp = gfc_evaluate_now (tmp, pre);
768 stmtblock_t do_copying;
770 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
771 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
772 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
773 tmp = gfc_get_element_type (tmp);
774 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
775 packed = gfc_create_var (build_pointer_type (tmp), "data");
777 tmp = build_call_expr_loc (input_location,
778 gfor_fndecl_in_pack, 1, initial);
779 tmp = fold_convert (TREE_TYPE (packed), tmp);
780 gfc_add_modify (pre, packed, tmp);
782 tmp = build_fold_indirect_ref_loc (input_location,
784 source_data = gfc_conv_descriptor_data_get (tmp);
786 /* internal_pack may return source->data without any allocation
787 or copying if it is already packed. If that's the case, we
788 need to allocate and copy manually. */
790 gfc_start_block (&do_copying);
791 tmp = gfc_call_malloc (&do_copying, NULL, size);
792 tmp = fold_convert (TREE_TYPE (packed), tmp);
793 gfc_add_modify (&do_copying, packed, tmp);
794 tmp = gfc_build_memcpy_call (packed, source_data, size);
795 gfc_add_expr_to_block (&do_copying, tmp);
797 was_packed = fold_build2_loc (input_location, EQ_EXPR,
798 boolean_type_node, packed,
800 tmp = gfc_finish_block (&do_copying);
801 tmp = build3_v (COND_EXPR, was_packed, tmp,
802 build_empty_stmt (input_location));
803 gfc_add_expr_to_block (pre, tmp);
805 tmp = fold_convert (pvoid_type_node, packed);
808 gfc_conv_descriptor_data_set (pre, desc, tmp);
811 info->data = gfc_conv_descriptor_data_get (desc);
813 /* The offset is zero because we create temporaries with a zero
815 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
817 if (dealloc && !onstack)
819 /* Free the temporary. */
820 tmp = gfc_conv_descriptor_data_get (desc);
821 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
822 gfc_add_expr_to_block (post, tmp);
827 /* Get the array reference dimension corresponding to the given loop dimension.
828 It is different from the true array dimension given by the dim array in
829 the case of a partial array reference
830 It is different from the loop dimension in the case of a transposed array.
834 get_array_ref_dim (gfc_ss *ss, int loop_dim)
836 int n, array_dim, array_ref_dim;
839 array_dim = ss->dim[loop_dim];
841 for (n = 0; n < ss->dimen; n++)
842 if (ss->dim[n] < array_dim)
845 return array_ref_dim;
849 /* Generate code to create and initialize the descriptor for a temporary
850 array. This is used for both temporaries needed by the scalarizer, and
851 functions returning arrays. Adjusts the loop variables to be
852 zero-based, and calculates the loop bounds for callee allocated arrays.
853 Allocate the array unless it's callee allocated (we have a callee
854 allocated array if 'callee_alloc' is true, or if loop->to[n] is
855 NULL_TREE for any n). Also fills in the descriptor, data and offset
856 fields of info if known. Returns the size of the array, or NULL for a
857 callee allocated array.
859 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
860 gfc_trans_allocate_array_storage.
864 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
865 gfc_loopinfo * loop, gfc_ss * ss,
866 tree eltype, tree initial, bool dynamic,
867 bool dealloc, bool callee_alloc, locus * where)
869 gfc_array_info *info;
870 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
880 memset (from, 0, sizeof (from));
881 memset (to, 0, sizeof (to));
883 info = &ss->info->data.array;
885 gcc_assert (ss->dimen > 0);
886 gcc_assert (loop->dimen == ss->dimen);
888 if (gfc_option.warn_array_temp && where)
889 gfc_warning ("Creating array temporary at %L", where);
891 /* Set the lower bound to zero. */
892 for (n = 0; n < loop->dimen; n++)
896 /* Callee allocated arrays may not have a known bound yet. */
898 loop->to[n] = gfc_evaluate_now (
899 fold_build2_loc (input_location, MINUS_EXPR,
900 gfc_array_index_type,
901 loop->to[n], loop->from[n]),
903 loop->from[n] = gfc_index_zero_node;
905 /* We are constructing the temporary's descriptor based on the loop
906 dimensions. As the dimensions may be accessed in arbitrary order
907 (think of transpose) the size taken from the n'th loop may not map
908 to the n'th dimension of the array. We need to reconstruct loop infos
909 in the right order before using it to set the descriptor
911 tmp_dim = get_array_ref_dim (ss, n);
912 from[tmp_dim] = loop->from[n];
913 to[tmp_dim] = loop->to[n];
915 info->delta[dim] = gfc_index_zero_node;
916 info->start[dim] = gfc_index_zero_node;
917 info->end[dim] = gfc_index_zero_node;
918 info->stride[dim] = gfc_index_one_node;
921 /* Initialize the descriptor. */
923 gfc_get_array_type_bounds (eltype, ss->dimen, 0, from, to, 1,
924 GFC_ARRAY_UNKNOWN, true);
925 desc = gfc_create_var (type, "atmp");
926 GFC_DECL_PACKED_ARRAY (desc) = 1;
928 info->descriptor = desc;
929 size = gfc_index_one_node;
931 /* Fill in the array dtype. */
932 tmp = gfc_conv_descriptor_dtype (desc);
933 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
936 Fill in the bounds and stride. This is a packed array, so:
939 for (n = 0; n < rank; n++)
942 delta = ubound[n] + 1 - lbound[n];
945 size = size * sizeof(element);
950 /* If there is at least one null loop->to[n], it is a callee allocated
952 for (n = 0; n < loop->dimen; n++)
953 if (loop->to[n] == NULL_TREE)
959 for (n = 0; n < loop->dimen; n++)
963 if (size == NULL_TREE)
965 /* For a callee allocated array express the loop bounds in terms
966 of the descriptor fields. */
967 tmp = fold_build2_loc (input_location,
968 MINUS_EXPR, gfc_array_index_type,
969 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
970 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
975 /* Store the stride and bound components in the descriptor. */
976 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
978 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
979 gfc_index_zero_node);
981 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n],
984 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
985 to[n], gfc_index_one_node);
987 /* Check whether the size for this dimension is negative. */
988 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, tmp,
989 gfc_index_zero_node);
990 cond = gfc_evaluate_now (cond, pre);
995 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
996 boolean_type_node, or_expr, cond);
998 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1000 size = gfc_evaluate_now (size, pre);
1003 /* Get the size of the array. */
1005 if (size && !callee_alloc)
1007 /* If or_expr is true, then the extent in at least one
1008 dimension is zero and the size is set to zero. */
1009 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1010 or_expr, gfc_index_zero_node, size);
1013 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1015 fold_convert (gfc_array_index_type,
1016 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
1024 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1027 if (ss->dimen > loop->temp_dim)
1028 loop->temp_dim = ss->dimen;
1034 /* Return the number of iterations in a loop that starts at START,
1035 ends at END, and has step STEP. */
1038 gfc_get_iteration_count (tree start, tree end, tree step)
1043 type = TREE_TYPE (step);
1044 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1045 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1046 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1047 build_int_cst (type, 1));
1048 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1049 build_int_cst (type, 0));
1050 return fold_convert (gfc_array_index_type, tmp);
1054 /* Extend the data in array DESC by EXTRA elements. */
1057 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1064 if (integer_zerop (extra))
1067 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1069 /* Add EXTRA to the upper bound. */
1070 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1072 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1074 /* Get the value of the current data pointer. */
1075 arg0 = gfc_conv_descriptor_data_get (desc);
1077 /* Calculate the new array size. */
1078 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1079 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1080 ubound, gfc_index_one_node);
1081 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1082 fold_convert (size_type_node, tmp),
1083 fold_convert (size_type_node, size));
1085 /* Call the realloc() function. */
1086 tmp = gfc_call_realloc (pblock, arg0, arg1);
1087 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1091 /* Return true if the bounds of iterator I can only be determined
1095 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1097 return (i->start->expr_type != EXPR_CONSTANT
1098 || i->end->expr_type != EXPR_CONSTANT
1099 || i->step->expr_type != EXPR_CONSTANT);
1103 /* Split the size of constructor element EXPR into the sum of two terms,
1104 one of which can be determined at compile time and one of which must
1105 be calculated at run time. Set *SIZE to the former and return true
1106 if the latter might be nonzero. */
1109 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1111 if (expr->expr_type == EXPR_ARRAY)
1112 return gfc_get_array_constructor_size (size, expr->value.constructor);
1113 else if (expr->rank > 0)
1115 /* Calculate everything at run time. */
1116 mpz_set_ui (*size, 0);
1121 /* A single element. */
1122 mpz_set_ui (*size, 1);
1128 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1129 of array constructor C. */
1132 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1140 mpz_set_ui (*size, 0);
1145 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1148 if (i && gfc_iterator_has_dynamic_bounds (i))
1152 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1155 /* Multiply the static part of the element size by the
1156 number of iterations. */
1157 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1158 mpz_fdiv_q (val, val, i->step->value.integer);
1159 mpz_add_ui (val, val, 1);
1160 if (mpz_sgn (val) > 0)
1161 mpz_mul (len, len, val);
1163 mpz_set_ui (len, 0);
1165 mpz_add (*size, *size, len);
1174 /* Make sure offset is a variable. */
1177 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1180 /* We should have already created the offset variable. We cannot
1181 create it here because we may be in an inner scope. */
1182 gcc_assert (*offsetvar != NULL_TREE);
1183 gfc_add_modify (pblock, *offsetvar, *poffset);
1184 *poffset = *offsetvar;
1185 TREE_USED (*offsetvar) = 1;
1189 /* Variables needed for bounds-checking. */
1190 static bool first_len;
1191 static tree first_len_val;
1192 static bool typespec_chararray_ctor;
1195 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1196 tree offset, gfc_se * se, gfc_expr * expr)
1200 gfc_conv_expr (se, expr);
1202 /* Store the value. */
1203 tmp = build_fold_indirect_ref_loc (input_location,
1204 gfc_conv_descriptor_data_get (desc));
1205 tmp = gfc_build_array_ref (tmp, offset, NULL);
1207 if (expr->ts.type == BT_CHARACTER)
1209 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1212 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1213 esize = fold_convert (gfc_charlen_type_node, esize);
1214 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1215 gfc_charlen_type_node, esize,
1216 build_int_cst (gfc_charlen_type_node,
1217 gfc_character_kinds[i].bit_size / 8));
1219 gfc_conv_string_parameter (se);
1220 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1222 /* The temporary is an array of pointers. */
1223 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1224 gfc_add_modify (&se->pre, tmp, se->expr);
1228 /* The temporary is an array of string values. */
1229 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1230 /* We know the temporary and the value will be the same length,
1231 so can use memcpy. */
1232 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1233 se->string_length, se->expr, expr->ts.kind);
1235 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1239 gfc_add_modify (&se->pre, first_len_val,
1245 /* Verify that all constructor elements are of the same
1247 tree cond = fold_build2_loc (input_location, NE_EXPR,
1248 boolean_type_node, first_len_val,
1250 gfc_trans_runtime_check
1251 (true, false, cond, &se->pre, &expr->where,
1252 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1253 fold_convert (long_integer_type_node, first_len_val),
1254 fold_convert (long_integer_type_node, se->string_length));
1260 /* TODO: Should the frontend already have done this conversion? */
1261 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1262 gfc_add_modify (&se->pre, tmp, se->expr);
1265 gfc_add_block_to_block (pblock, &se->pre);
1266 gfc_add_block_to_block (pblock, &se->post);
1270 /* Add the contents of an array to the constructor. DYNAMIC is as for
1271 gfc_trans_array_constructor_value. */
1274 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1275 tree type ATTRIBUTE_UNUSED,
1276 tree desc, gfc_expr * expr,
1277 tree * poffset, tree * offsetvar,
1288 /* We need this to be a variable so we can increment it. */
1289 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1291 gfc_init_se (&se, NULL);
1293 /* Walk the array expression. */
1294 ss = gfc_walk_expr (expr);
1295 gcc_assert (ss != gfc_ss_terminator);
1297 /* Initialize the scalarizer. */
1298 gfc_init_loopinfo (&loop);
1299 gfc_add_ss_to_loop (&loop, ss);
1301 /* Initialize the loop. */
1302 gfc_conv_ss_startstride (&loop);
1303 gfc_conv_loop_setup (&loop, &expr->where);
1305 /* Make sure the constructed array has room for the new data. */
1308 /* Set SIZE to the total number of elements in the subarray. */
1309 size = gfc_index_one_node;
1310 for (n = 0; n < loop.dimen; n++)
1312 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1313 gfc_index_one_node);
1314 size = fold_build2_loc (input_location, MULT_EXPR,
1315 gfc_array_index_type, size, tmp);
1318 /* Grow the constructed array by SIZE elements. */
1319 gfc_grow_array (&loop.pre, desc, size);
1322 /* Make the loop body. */
1323 gfc_mark_ss_chain_used (ss, 1);
1324 gfc_start_scalarized_body (&loop, &body);
1325 gfc_copy_loopinfo_to_se (&se, &loop);
1328 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1329 gcc_assert (se.ss == gfc_ss_terminator);
1331 /* Increment the offset. */
1332 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1333 *poffset, gfc_index_one_node);
1334 gfc_add_modify (&body, *poffset, tmp);
1336 /* Finish the loop. */
1337 gfc_trans_scalarizing_loops (&loop, &body);
1338 gfc_add_block_to_block (&loop.pre, &loop.post);
1339 tmp = gfc_finish_block (&loop.pre);
1340 gfc_add_expr_to_block (pblock, tmp);
1342 gfc_cleanup_loop (&loop);
1346 /* Assign the values to the elements of an array constructor. DYNAMIC
1347 is true if descriptor DESC only contains enough data for the static
1348 size calculated by gfc_get_array_constructor_size. When true, memory
1349 for the dynamic parts must be allocated using realloc. */
1352 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1353 tree desc, gfc_constructor_base base,
1354 tree * poffset, tree * offsetvar,
1363 tree shadow_loopvar = NULL_TREE;
1364 gfc_saved_var saved_loopvar;
1367 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1369 /* If this is an iterator or an array, the offset must be a variable. */
1370 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1371 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1373 /* Shadowing the iterator avoids changing its value and saves us from
1374 keeping track of it. Further, it makes sure that there's always a
1375 backend-decl for the symbol, even if there wasn't one before,
1376 e.g. in the case of an iterator that appears in a specification
1377 expression in an interface mapping. */
1380 gfc_symbol *sym = c->iterator->var->symtree->n.sym;
1381 tree type = gfc_typenode_for_spec (&sym->ts);
1383 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1384 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1387 gfc_start_block (&body);
1389 if (c->expr->expr_type == EXPR_ARRAY)
1391 /* Array constructors can be nested. */
1392 gfc_trans_array_constructor_value (&body, type, desc,
1393 c->expr->value.constructor,
1394 poffset, offsetvar, dynamic);
1396 else if (c->expr->rank > 0)
1398 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1399 poffset, offsetvar, dynamic);
1403 /* This code really upsets the gimplifier so don't bother for now. */
1410 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1412 p = gfc_constructor_next (p);
1417 /* Scalar values. */
1418 gfc_init_se (&se, NULL);
1419 gfc_trans_array_ctor_element (&body, desc, *poffset,
1422 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1423 gfc_array_index_type,
1424 *poffset, gfc_index_one_node);
1428 /* Collect multiple scalar constants into a constructor. */
1429 VEC(constructor_elt,gc) *v = NULL;
1433 HOST_WIDE_INT idx = 0;
1436 /* Count the number of consecutive scalar constants. */
1437 while (p && !(p->iterator
1438 || p->expr->expr_type != EXPR_CONSTANT))
1440 gfc_init_se (&se, NULL);
1441 gfc_conv_constant (&se, p->expr);
1443 if (c->expr->ts.type != BT_CHARACTER)
1444 se.expr = fold_convert (type, se.expr);
1445 /* For constant character array constructors we build
1446 an array of pointers. */
1447 else if (POINTER_TYPE_P (type))
1448 se.expr = gfc_build_addr_expr
1449 (gfc_get_pchar_type (p->expr->ts.kind),
1452 CONSTRUCTOR_APPEND_ELT (v,
1453 build_int_cst (gfc_array_index_type,
1457 p = gfc_constructor_next (p);
1460 bound = size_int (n - 1);
1461 /* Create an array type to hold them. */
1462 tmptype = build_range_type (gfc_array_index_type,
1463 gfc_index_zero_node, bound);
1464 tmptype = build_array_type (type, tmptype);
1466 init = build_constructor (tmptype, v);
1467 TREE_CONSTANT (init) = 1;
1468 TREE_STATIC (init) = 1;
1469 /* Create a static variable to hold the data. */
1470 tmp = gfc_create_var (tmptype, "data");
1471 TREE_STATIC (tmp) = 1;
1472 TREE_CONSTANT (tmp) = 1;
1473 TREE_READONLY (tmp) = 1;
1474 DECL_INITIAL (tmp) = init;
1477 /* Use BUILTIN_MEMCPY to assign the values. */
1478 tmp = gfc_conv_descriptor_data_get (desc);
1479 tmp = build_fold_indirect_ref_loc (input_location,
1481 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1482 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1483 init = gfc_build_addr_expr (NULL_TREE, init);
1485 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1486 bound = build_int_cst (size_type_node, n * size);
1487 tmp = build_call_expr_loc (input_location,
1488 builtin_decl_explicit (BUILT_IN_MEMCPY),
1489 3, tmp, init, bound);
1490 gfc_add_expr_to_block (&body, tmp);
1492 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1493 gfc_array_index_type, *poffset,
1494 build_int_cst (gfc_array_index_type, n));
1496 if (!INTEGER_CST_P (*poffset))
1498 gfc_add_modify (&body, *offsetvar, *poffset);
1499 *poffset = *offsetvar;
1503 /* The frontend should already have done any expansions
1507 /* Pass the code as is. */
1508 tmp = gfc_finish_block (&body);
1509 gfc_add_expr_to_block (pblock, tmp);
1513 /* Build the implied do-loop. */
1514 stmtblock_t implied_do_block;
1522 loopbody = gfc_finish_block (&body);
1524 /* Create a new block that holds the implied-do loop. A temporary
1525 loop-variable is used. */
1526 gfc_start_block(&implied_do_block);
1528 /* Initialize the loop. */
1529 gfc_init_se (&se, NULL);
1530 gfc_conv_expr_val (&se, c->iterator->start);
1531 gfc_add_block_to_block (&implied_do_block, &se.pre);
1532 gfc_add_modify (&implied_do_block, shadow_loopvar, se.expr);
1534 gfc_init_se (&se, NULL);
1535 gfc_conv_expr_val (&se, c->iterator->end);
1536 gfc_add_block_to_block (&implied_do_block, &se.pre);
1537 end = gfc_evaluate_now (se.expr, &implied_do_block);
1539 gfc_init_se (&se, NULL);
1540 gfc_conv_expr_val (&se, c->iterator->step);
1541 gfc_add_block_to_block (&implied_do_block, &se.pre);
1542 step = gfc_evaluate_now (se.expr, &implied_do_block);
1544 /* If this array expands dynamically, and the number of iterations
1545 is not constant, we won't have allocated space for the static
1546 part of C->EXPR's size. Do that now. */
1547 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1549 /* Get the number of iterations. */
1550 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1552 /* Get the static part of C->EXPR's size. */
1553 gfc_get_array_constructor_element_size (&size, c->expr);
1554 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1556 /* Grow the array by TMP * TMP2 elements. */
1557 tmp = fold_build2_loc (input_location, MULT_EXPR,
1558 gfc_array_index_type, tmp, tmp2);
1559 gfc_grow_array (&implied_do_block, desc, tmp);
1562 /* Generate the loop body. */
1563 exit_label = gfc_build_label_decl (NULL_TREE);
1564 gfc_start_block (&body);
1566 /* Generate the exit condition. Depending on the sign of
1567 the step variable we have to generate the correct
1569 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1570 step, build_int_cst (TREE_TYPE (step), 0));
1571 cond = fold_build3_loc (input_location, COND_EXPR,
1572 boolean_type_node, tmp,
1573 fold_build2_loc (input_location, GT_EXPR,
1574 boolean_type_node, shadow_loopvar, end),
1575 fold_build2_loc (input_location, LT_EXPR,
1576 boolean_type_node, shadow_loopvar, end));
1577 tmp = build1_v (GOTO_EXPR, exit_label);
1578 TREE_USED (exit_label) = 1;
1579 tmp = build3_v (COND_EXPR, cond, tmp,
1580 build_empty_stmt (input_location));
1581 gfc_add_expr_to_block (&body, tmp);
1583 /* The main loop body. */
1584 gfc_add_expr_to_block (&body, loopbody);
1586 /* Increase loop variable by step. */
1587 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1588 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1590 gfc_add_modify (&body, shadow_loopvar, tmp);
1592 /* Finish the loop. */
1593 tmp = gfc_finish_block (&body);
1594 tmp = build1_v (LOOP_EXPR, tmp);
1595 gfc_add_expr_to_block (&implied_do_block, tmp);
1597 /* Add the exit label. */
1598 tmp = build1_v (LABEL_EXPR, exit_label);
1599 gfc_add_expr_to_block (&implied_do_block, tmp);
1601 /* Finishe the implied-do loop. */
1602 tmp = gfc_finish_block(&implied_do_block);
1603 gfc_add_expr_to_block(pblock, tmp);
1605 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1612 /* A catch-all to obtain the string length for anything that is not a
1613 a substring of non-constant length, a constant, array or variable. */
1616 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1621 /* Don't bother if we already know the length is a constant. */
1622 if (*len && INTEGER_CST_P (*len))
1625 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1626 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1629 gfc_conv_const_charlen (e->ts.u.cl);
1630 *len = e->ts.u.cl->backend_decl;
1634 /* Otherwise, be brutal even if inefficient. */
1635 ss = gfc_walk_expr (e);
1636 gfc_init_se (&se, NULL);
1638 /* No function call, in case of side effects. */
1639 se.no_function_call = 1;
1640 if (ss == gfc_ss_terminator)
1641 gfc_conv_expr (&se, e);
1643 gfc_conv_expr_descriptor (&se, e, ss);
1645 /* Fix the value. */
1646 *len = gfc_evaluate_now (se.string_length, &se.pre);
1648 gfc_add_block_to_block (block, &se.pre);
1649 gfc_add_block_to_block (block, &se.post);
1651 e->ts.u.cl->backend_decl = *len;
1656 /* Figure out the string length of a variable reference expression.
1657 Used by get_array_ctor_strlen. */
1660 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
1666 /* Don't bother if we already know the length is a constant. */
1667 if (*len && INTEGER_CST_P (*len))
1670 ts = &expr->symtree->n.sym->ts;
1671 for (ref = expr->ref; ref; ref = ref->next)
1676 /* Array references don't change the string length. */
1680 /* Use the length of the component. */
1681 ts = &ref->u.c.component->ts;
1685 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1686 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1688 /* Note that this might evaluate expr. */
1689 get_array_ctor_all_strlen (block, expr, len);
1692 mpz_init_set_ui (char_len, 1);
1693 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1694 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1695 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1696 *len = convert (gfc_charlen_type_node, *len);
1697 mpz_clear (char_len);
1705 *len = ts->u.cl->backend_decl;
1709 /* Figure out the string length of a character array constructor.
1710 If len is NULL, don't calculate the length; this happens for recursive calls
1711 when a sub-array-constructor is an element but not at the first position,
1712 so when we're not interested in the length.
1713 Returns TRUE if all elements are character constants. */
1716 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
1723 if (gfc_constructor_first (base) == NULL)
1726 *len = build_int_cstu (gfc_charlen_type_node, 0);
1730 /* Loop over all constructor elements to find out is_const, but in len we
1731 want to store the length of the first, not the last, element. We can
1732 of course exit the loop as soon as is_const is found to be false. */
1733 for (c = gfc_constructor_first (base);
1734 c && is_const; c = gfc_constructor_next (c))
1736 switch (c->expr->expr_type)
1739 if (len && !(*len && INTEGER_CST_P (*len)))
1740 *len = build_int_cstu (gfc_charlen_type_node,
1741 c->expr->value.character.length);
1745 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1752 get_array_ctor_var_strlen (block, c->expr, len);
1758 get_array_ctor_all_strlen (block, c->expr, len);
1762 /* After the first iteration, we don't want the length modified. */
1769 /* Check whether the array constructor C consists entirely of constant
1770 elements, and if so returns the number of those elements, otherwise
1771 return zero. Note, an empty or NULL array constructor returns zero. */
1773 unsigned HOST_WIDE_INT
1774 gfc_constant_array_constructor_p (gfc_constructor_base base)
1776 unsigned HOST_WIDE_INT nelem = 0;
1778 gfc_constructor *c = gfc_constructor_first (base);
1782 || c->expr->rank > 0
1783 || c->expr->expr_type != EXPR_CONSTANT)
1785 c = gfc_constructor_next (c);
1792 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1793 and the tree type of it's elements, TYPE, return a static constant
1794 variable that is compile-time initialized. */
1797 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1799 tree tmptype, init, tmp;
1800 HOST_WIDE_INT nelem;
1805 VEC(constructor_elt,gc) *v = NULL;
1807 /* First traverse the constructor list, converting the constants
1808 to tree to build an initializer. */
1810 c = gfc_constructor_first (expr->value.constructor);
1813 gfc_init_se (&se, NULL);
1814 gfc_conv_constant (&se, c->expr);
1815 if (c->expr->ts.type != BT_CHARACTER)
1816 se.expr = fold_convert (type, se.expr);
1817 else if (POINTER_TYPE_P (type))
1818 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
1820 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
1822 c = gfc_constructor_next (c);
1826 /* Next determine the tree type for the array. We use the gfortran
1827 front-end's gfc_get_nodesc_array_type in order to create a suitable
1828 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1830 memset (&as, 0, sizeof (gfc_array_spec));
1832 as.rank = expr->rank;
1833 as.type = AS_EXPLICIT;
1836 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1837 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
1841 for (i = 0; i < expr->rank; i++)
1843 int tmp = (int) mpz_get_si (expr->shape[i]);
1844 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1845 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
1849 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
1851 /* as is not needed anymore. */
1852 for (i = 0; i < as.rank + as.corank; i++)
1854 gfc_free_expr (as.lower[i]);
1855 gfc_free_expr (as.upper[i]);
1858 init = build_constructor (tmptype, v);
1860 TREE_CONSTANT (init) = 1;
1861 TREE_STATIC (init) = 1;
1863 tmp = gfc_create_var (tmptype, "A");
1864 TREE_STATIC (tmp) = 1;
1865 TREE_CONSTANT (tmp) = 1;
1866 TREE_READONLY (tmp) = 1;
1867 DECL_INITIAL (tmp) = init;
1873 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1874 This mostly initializes the scalarizer state info structure with the
1875 appropriate values to directly use the array created by the function
1876 gfc_build_constant_array_constructor. */
1879 trans_constant_array_constructor (gfc_ss * ss, tree type)
1881 gfc_array_info *info;
1885 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
1887 info = &ss->info->data.array;
1889 info->descriptor = tmp;
1890 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
1891 info->offset = gfc_index_zero_node;
1893 for (i = 0; i < ss->dimen; i++)
1895 info->delta[i] = gfc_index_zero_node;
1896 info->start[i] = gfc_index_zero_node;
1897 info->end[i] = gfc_index_zero_node;
1898 info->stride[i] = gfc_index_one_node;
1902 /* Helper routine of gfc_trans_array_constructor to determine if the
1903 bounds of the loop specified by LOOP are constant and simple enough
1904 to use with trans_constant_array_constructor. Returns the
1905 iteration count of the loop if suitable, and NULL_TREE otherwise. */
1908 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1910 tree size = gfc_index_one_node;
1914 for (i = 0; i < loop->dimen; i++)
1916 /* If the bounds aren't constant, return NULL_TREE. */
1917 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1919 if (!integer_zerop (loop->from[i]))
1921 /* Only allow nonzero "from" in one-dimensional arrays. */
1922 if (loop->dimen != 1)
1924 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1925 gfc_array_index_type,
1926 loop->to[i], loop->from[i]);
1930 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1931 tmp, gfc_index_one_node);
1932 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1940 /* Array constructors are handled by constructing a temporary, then using that
1941 within the scalarization loop. This is not optimal, but seems by far the
1945 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
1947 gfc_constructor_base c;
1954 bool old_first_len, old_typespec_chararray_ctor;
1955 tree old_first_len_val;
1956 gfc_ss_info *ss_info;
1959 /* Save the old values for nested checking. */
1960 old_first_len = first_len;
1961 old_first_len_val = first_len_val;
1962 old_typespec_chararray_ctor = typespec_chararray_ctor;
1965 expr = ss_info->expr;
1967 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
1968 typespec was given for the array constructor. */
1969 typespec_chararray_ctor = (expr->ts.u.cl
1970 && expr->ts.u.cl->length_from_typespec);
1972 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1973 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
1975 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1979 gcc_assert (ss->dimen == loop->dimen);
1981 c = expr->value.constructor;
1982 if (expr->ts.type == BT_CHARACTER)
1986 /* get_array_ctor_strlen walks the elements of the constructor, if a
1987 typespec was given, we already know the string length and want the one
1989 if (typespec_chararray_ctor && expr->ts.u.cl->length
1990 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
1994 const_string = false;
1995 gfc_init_se (&length_se, NULL);
1996 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
1997 gfc_charlen_type_node);
1998 ss_info->string_length = length_se.expr;
1999 gfc_add_block_to_block (&loop->pre, &length_se.pre);
2000 gfc_add_block_to_block (&loop->post, &length_se.post);
2003 const_string = get_array_ctor_strlen (&loop->pre, c,
2004 &ss_info->string_length);
2006 /* Complex character array constructors should have been taken care of
2007 and not end up here. */
2008 gcc_assert (ss_info->string_length);
2010 expr->ts.u.cl->backend_decl = ss_info->string_length;
2012 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2014 type = build_pointer_type (type);
2017 type = gfc_typenode_for_spec (&expr->ts);
2019 /* See if the constructor determines the loop bounds. */
2022 if (expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
2024 /* We have a multidimensional parameter. */
2026 for (n = 0; n < expr->rank; n++)
2028 loop->from[n] = gfc_index_zero_node;
2029 loop->to[n] = gfc_conv_mpz_to_tree (expr->shape [n],
2030 gfc_index_integer_kind);
2031 loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2032 gfc_array_index_type,
2033 loop->to[n], gfc_index_one_node);
2037 if (loop->to[0] == NULL_TREE)
2041 /* We should have a 1-dimensional, zero-based loop. */
2042 gcc_assert (loop->dimen == 1);
2043 gcc_assert (integer_zerop (loop->from[0]));
2045 /* Split the constructor size into a static part and a dynamic part.
2046 Allocate the static size up-front and record whether the dynamic
2047 size might be nonzero. */
2049 dynamic = gfc_get_array_constructor_size (&size, c);
2050 mpz_sub_ui (size, size, 1);
2051 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2055 /* Special case constant array constructors. */
2058 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2061 tree size = constant_array_constructor_loop_size (loop);
2062 if (size && compare_tree_int (size, nelem) == 0)
2064 trans_constant_array_constructor (ss, type);
2070 if (TREE_CODE (loop->to[0]) == VAR_DECL)
2073 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, ss,
2074 type, NULL_TREE, dynamic, true, false, where);
2076 desc = ss_info->data.array.descriptor;
2077 offset = gfc_index_zero_node;
2078 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2079 TREE_NO_WARNING (offsetvar) = 1;
2080 TREE_USED (offsetvar) = 0;
2081 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
2082 &offset, &offsetvar, dynamic);
2084 /* If the array grows dynamically, the upper bound of the loop variable
2085 is determined by the array's final upper bound. */
2088 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2089 gfc_array_index_type,
2090 offsetvar, gfc_index_one_node);
2091 tmp = gfc_evaluate_now (tmp, &loop->pre);
2092 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2093 if (loop->to[0] && TREE_CODE (loop->to[0]) == VAR_DECL)
2094 gfc_add_modify (&loop->pre, loop->to[0], tmp);
2099 if (TREE_USED (offsetvar))
2100 pushdecl (offsetvar);
2102 gcc_assert (INTEGER_CST_P (offset));
2105 /* Disable bound checking for now because it's probably broken. */
2106 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2113 /* Restore old values of globals. */
2114 first_len = old_first_len;
2115 first_len_val = old_first_len_val;
2116 typespec_chararray_ctor = old_typespec_chararray_ctor;
2120 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2121 called after evaluating all of INFO's vector dimensions. Go through
2122 each such vector dimension and see if we can now fill in any missing
2126 set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss * ss)
2128 gfc_array_info *info;
2136 info = &ss->info->data.array;
2138 for (n = 0; n < loop->dimen; n++)
2141 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
2142 && loop->to[n] == NULL)
2144 /* Loop variable N indexes vector dimension DIM, and we don't
2145 yet know the upper bound of loop variable N. Set it to the
2146 difference between the vector's upper and lower bounds. */
2147 gcc_assert (loop->from[n] == gfc_index_zero_node);
2148 gcc_assert (info->subscript[dim]
2149 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2151 gfc_init_se (&se, NULL);
2152 desc = info->subscript[dim]->info->data.array.descriptor;
2153 zero = gfc_rank_cst[0];
2154 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2155 gfc_array_index_type,
2156 gfc_conv_descriptor_ubound_get (desc, zero),
2157 gfc_conv_descriptor_lbound_get (desc, zero));
2158 tmp = gfc_evaluate_now (tmp, &loop->pre);
2165 /* Add the pre and post chains for all the scalar expressions in a SS chain
2166 to loop. This is called after the loop parameters have been calculated,
2167 but before the actual scalarizing loops. */
2170 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2174 gfc_ss_info *ss_info;
2175 gfc_array_info *info;
2179 /* TODO: This can generate bad code if there are ordering dependencies,
2180 e.g., a callee allocated function and an unknown size constructor. */
2181 gcc_assert (ss != NULL);
2183 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2188 expr = ss_info->expr;
2189 info = &ss_info->data.array;
2191 switch (ss_info->type)
2194 /* Scalar expression. Evaluate this now. This includes elemental
2195 dimension indices, but not array section bounds. */
2196 gfc_init_se (&se, NULL);
2197 gfc_conv_expr (&se, expr);
2198 gfc_add_block_to_block (&loop->pre, &se.pre);
2200 if (expr->ts.type != BT_CHARACTER)
2202 /* Move the evaluation of scalar expressions outside the
2203 scalarization loop, except for WHERE assignments. */
2205 se.expr = convert(gfc_array_index_type, se.expr);
2207 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
2208 gfc_add_block_to_block (&loop->pre, &se.post);
2211 gfc_add_block_to_block (&loop->post, &se.post);
2213 ss_info->data.scalar.value = se.expr;
2214 ss_info->string_length = se.string_length;
2217 case GFC_SS_REFERENCE:
2218 /* Scalar argument to elemental procedure. Evaluate this
2220 gfc_init_se (&se, NULL);
2221 gfc_conv_expr (&se, expr);
2222 gfc_add_block_to_block (&loop->pre, &se.pre);
2223 gfc_add_block_to_block (&loop->post, &se.post);
2225 ss_info->data.scalar.value = gfc_evaluate_now (se.expr, &loop->pre);
2226 ss_info->string_length = se.string_length;
2229 case GFC_SS_SECTION:
2230 /* Add the expressions for scalar and vector subscripts. */
2231 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2232 if (info->subscript[n])
2233 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2235 set_vector_loop_bounds (loop, ss);
2239 /* Get the vector's descriptor and store it in SS. */
2240 gfc_init_se (&se, NULL);
2241 gfc_conv_expr_descriptor (&se, expr, gfc_walk_expr (expr));
2242 gfc_add_block_to_block (&loop->pre, &se.pre);
2243 gfc_add_block_to_block (&loop->post, &se.post);
2244 info->descriptor = se.expr;
2247 case GFC_SS_INTRINSIC:
2248 gfc_add_intrinsic_ss_code (loop, ss);
2251 case GFC_SS_FUNCTION:
2252 /* Array function return value. We call the function and save its
2253 result in a temporary for use inside the loop. */
2254 gfc_init_se (&se, NULL);
2257 gfc_conv_expr (&se, expr);
2258 gfc_add_block_to_block (&loop->pre, &se.pre);
2259 gfc_add_block_to_block (&loop->post, &se.post);
2260 ss_info->string_length = se.string_length;
2263 case GFC_SS_CONSTRUCTOR:
2264 if (expr->ts.type == BT_CHARACTER
2265 && ss_info->string_length == NULL
2267 && expr->ts.u.cl->length)
2269 gfc_init_se (&se, NULL);
2270 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2271 gfc_charlen_type_node);
2272 ss_info->string_length = se.expr;
2273 gfc_add_block_to_block (&loop->pre, &se.pre);
2274 gfc_add_block_to_block (&loop->post, &se.post);
2276 gfc_trans_array_constructor (loop, ss, where);
2280 case GFC_SS_COMPONENT:
2281 /* Do nothing. These are handled elsewhere. */
2291 /* Translate expressions for the descriptor and data pointer of a SS. */
2295 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2298 gfc_ss_info *ss_info;
2299 gfc_array_info *info;
2303 info = &ss_info->data.array;
2305 /* Get the descriptor for the array to be scalarized. */
2306 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2307 gfc_init_se (&se, NULL);
2308 se.descriptor_only = 1;
2309 gfc_conv_expr_lhs (&se, ss_info->expr);
2310 gfc_add_block_to_block (block, &se.pre);
2311 info->descriptor = se.expr;
2312 ss_info->string_length = se.string_length;
2316 /* Also the data pointer. */
2317 tmp = gfc_conv_array_data (se.expr);
2318 /* If this is a variable or address of a variable we use it directly.
2319 Otherwise we must evaluate it now to avoid breaking dependency
2320 analysis by pulling the expressions for elemental array indices
2323 || (TREE_CODE (tmp) == ADDR_EXPR
2324 && DECL_P (TREE_OPERAND (tmp, 0)))))
2325 tmp = gfc_evaluate_now (tmp, block);
2328 tmp = gfc_conv_array_offset (se.expr);
2329 info->offset = gfc_evaluate_now (tmp, block);
2331 /* Make absolutely sure that the saved_offset is indeed saved
2332 so that the variable is still accessible after the loops
2334 info->saved_offset = info->offset;
2339 /* Initialize a gfc_loopinfo structure. */
2342 gfc_init_loopinfo (gfc_loopinfo * loop)
2346 memset (loop, 0, sizeof (gfc_loopinfo));
2347 gfc_init_block (&loop->pre);
2348 gfc_init_block (&loop->post);
2350 /* Initially scalarize in order and default to no loop reversal. */
2351 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2354 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2357 loop->ss = gfc_ss_terminator;
2361 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2365 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2371 /* Return an expression for the data pointer of an array. */
2374 gfc_conv_array_data (tree descriptor)
2378 type = TREE_TYPE (descriptor);
2379 if (GFC_ARRAY_TYPE_P (type))
2381 if (TREE_CODE (type) == POINTER_TYPE)
2385 /* Descriptorless arrays. */
2386 return gfc_build_addr_expr (NULL_TREE, descriptor);
2390 return gfc_conv_descriptor_data_get (descriptor);
2394 /* Return an expression for the base offset of an array. */
2397 gfc_conv_array_offset (tree descriptor)
2401 type = TREE_TYPE (descriptor);
2402 if (GFC_ARRAY_TYPE_P (type))
2403 return GFC_TYPE_ARRAY_OFFSET (type);
2405 return gfc_conv_descriptor_offset_get (descriptor);
2409 /* Get an expression for the array stride. */
2412 gfc_conv_array_stride (tree descriptor, int dim)
2417 type = TREE_TYPE (descriptor);
2419 /* For descriptorless arrays use the array size. */
2420 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2421 if (tmp != NULL_TREE)
2424 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2429 /* Like gfc_conv_array_stride, but for the lower bound. */
2432 gfc_conv_array_lbound (tree descriptor, int dim)
2437 type = TREE_TYPE (descriptor);
2439 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2440 if (tmp != NULL_TREE)
2443 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2448 /* Like gfc_conv_array_stride, but for the upper bound. */
2451 gfc_conv_array_ubound (tree descriptor, int dim)
2456 type = TREE_TYPE (descriptor);
2458 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2459 if (tmp != NULL_TREE)
2462 /* This should only ever happen when passing an assumed shape array
2463 as an actual parameter. The value will never be used. */
2464 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2465 return gfc_index_zero_node;
2467 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2472 /* Generate code to perform an array index bound check. */
2475 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
2476 locus * where, bool check_upper)
2479 tree tmp_lo, tmp_up;
2482 const char * name = NULL;
2484 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2487 descriptor = ss->info->data.array.descriptor;
2489 index = gfc_evaluate_now (index, &se->pre);
2491 /* We find a name for the error message. */
2492 name = ss->info->expr->symtree->n.sym->name;
2493 gcc_assert (name != NULL);
2495 if (TREE_CODE (descriptor) == VAR_DECL)
2496 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
2498 /* If upper bound is present, include both bounds in the error message. */
2501 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2502 tmp_up = gfc_conv_array_ubound (descriptor, n);
2505 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2506 "outside of expected range (%%ld:%%ld)", n+1, name);
2508 asprintf (&msg, "Index '%%ld' of dimension %d "
2509 "outside of expected range (%%ld:%%ld)", n+1);
2511 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2513 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2514 fold_convert (long_integer_type_node, index),
2515 fold_convert (long_integer_type_node, tmp_lo),
2516 fold_convert (long_integer_type_node, tmp_up));
2517 fault = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2519 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2520 fold_convert (long_integer_type_node, index),
2521 fold_convert (long_integer_type_node, tmp_lo),
2522 fold_convert (long_integer_type_node, tmp_up));
2527 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2530 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2531 "below lower bound of %%ld", n+1, name);
2533 asprintf (&msg, "Index '%%ld' of dimension %d "
2534 "below lower bound of %%ld", n+1);
2536 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2538 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2539 fold_convert (long_integer_type_node, index),
2540 fold_convert (long_integer_type_node, tmp_lo));
2548 /* Return the offset for an index. Performs bound checking for elemental
2549 dimensions. Single element references are processed separately.
2550 DIM is the array dimension, I is the loop dimension. */
2553 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
2554 gfc_array_ref * ar, tree stride)
2556 gfc_array_info *info;
2561 info = &ss->info->data.array;
2563 /* Get the index into the array for this dimension. */
2566 gcc_assert (ar->type != AR_ELEMENT);
2567 switch (ar->dimen_type[dim])
2569 case DIMEN_THIS_IMAGE:
2573 /* Elemental dimension. */
2574 gcc_assert (info->subscript[dim]
2575 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
2576 /* We've already translated this value outside the loop. */
2577 index = info->subscript[dim]->info->data.scalar.value;
2579 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2580 ar->as->type != AS_ASSUMED_SIZE
2581 || dim < ar->dimen - 1);
2585 gcc_assert (info && se->loop);
2586 gcc_assert (info->subscript[dim]
2587 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2588 desc = info->subscript[dim]->info->data.array.descriptor;
2590 /* Get a zero-based index into the vector. */
2591 index = fold_build2_loc (input_location, MINUS_EXPR,
2592 gfc_array_index_type,
2593 se->loop->loopvar[i], se->loop->from[i]);
2595 /* Multiply the index by the stride. */
2596 index = fold_build2_loc (input_location, MULT_EXPR,
2597 gfc_array_index_type,
2598 index, gfc_conv_array_stride (desc, 0));
2600 /* Read the vector to get an index into info->descriptor. */
2601 data = build_fold_indirect_ref_loc (input_location,
2602 gfc_conv_array_data (desc));
2603 index = gfc_build_array_ref (data, index, NULL);
2604 index = gfc_evaluate_now (index, &se->pre);
2605 index = fold_convert (gfc_array_index_type, index);
2607 /* Do any bounds checking on the final info->descriptor index. */
2608 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2609 ar->as->type != AS_ASSUMED_SIZE
2610 || dim < ar->dimen - 1);
2614 /* Scalarized dimension. */
2615 gcc_assert (info && se->loop);
2617 /* Multiply the loop variable by the stride and delta. */
2618 index = se->loop->loopvar[i];
2619 if (!integer_onep (info->stride[dim]))
2620 index = fold_build2_loc (input_location, MULT_EXPR,
2621 gfc_array_index_type, index,
2623 if (!integer_zerop (info->delta[dim]))
2624 index = fold_build2_loc (input_location, PLUS_EXPR,
2625 gfc_array_index_type, index,
2635 /* Temporary array or derived type component. */
2636 gcc_assert (se->loop);
2637 index = se->loop->loopvar[se->loop->order[i]];
2639 /* Pointer functions can have stride[0] different from unity.
2640 Use the stride returned by the function call and stored in
2641 the descriptor for the temporary. */
2642 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
2643 && se->ss->info->expr
2644 && se->ss->info->expr->symtree
2645 && se->ss->info->expr->symtree->n.sym->result
2646 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
2647 stride = gfc_conv_descriptor_stride_get (info->descriptor,
2650 if (!integer_zerop (info->delta[dim]))
2651 index = fold_build2_loc (input_location, PLUS_EXPR,
2652 gfc_array_index_type, index, info->delta[dim]);
2655 /* Multiply by the stride. */
2656 if (!integer_onep (stride))
2657 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2664 /* Build a scalarized reference to an array. */
2667 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2669 gfc_array_info *info;
2670 tree decl = NULL_TREE;
2678 expr = ss->info->expr;
2679 info = &ss->info->data.array;
2681 n = se->loop->order[0];
2685 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
2686 /* Add the offset for this dimension to the stored offset for all other
2688 if (!integer_zerop (info->offset))
2689 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2690 index, info->offset);
2692 if (expr && is_subref_array (expr))
2693 decl = expr->symtree->n.sym->backend_decl;
2695 tmp = build_fold_indirect_ref_loc (input_location, info->data);
2696 se->expr = gfc_build_array_ref (tmp, index, decl);
2700 /* Translate access of temporary array. */
2703 gfc_conv_tmp_array_ref (gfc_se * se)
2705 se->string_length = se->ss->info->string_length;
2706 gfc_conv_scalarized_array_ref (se, NULL);
2707 gfc_advance_se_ss_chain (se);
2710 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
2713 add_to_offset (tree *cst_offset, tree *offset, tree t)
2715 if (TREE_CODE (t) == INTEGER_CST)
2716 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
2719 if (!integer_zerop (*offset))
2720 *offset = fold_build2_loc (input_location, PLUS_EXPR,
2721 gfc_array_index_type, *offset, t);
2727 /* Build an array reference. se->expr already holds the array descriptor.
2728 This should be either a variable, indirect variable reference or component
2729 reference. For arrays which do not have a descriptor, se->expr will be
2731 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2734 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2738 tree offset, cst_offset;
2746 gcc_assert (ar->codimen);
2748 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
2749 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
2752 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
2753 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
2754 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
2756 /* Use the actual tree type and not the wrapped coarray. */
2757 if (!se->want_pointer)
2758 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
2765 /* Handle scalarized references separately. */
2766 if (ar->type != AR_ELEMENT)
2768 gfc_conv_scalarized_array_ref (se, ar);
2769 gfc_advance_se_ss_chain (se);
2773 cst_offset = offset = gfc_index_zero_node;
2774 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
2776 /* Calculate the offsets from all the dimensions. Make sure to associate
2777 the final offset so that we form a chain of loop invariant summands. */
2778 for (n = ar->dimen - 1; n >= 0; n--)
2780 /* Calculate the index for this dimension. */
2781 gfc_init_se (&indexse, se);
2782 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2783 gfc_add_block_to_block (&se->pre, &indexse.pre);
2785 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2787 /* Check array bounds. */
2791 /* Evaluate the indexse.expr only once. */
2792 indexse.expr = save_expr (indexse.expr);
2795 tmp = gfc_conv_array_lbound (se->expr, n);
2796 if (sym->attr.temporary)
2798 gfc_init_se (&tmpse, se);
2799 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
2800 gfc_array_index_type);
2801 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2805 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2807 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2808 "below lower bound of %%ld", n+1, sym->name);
2809 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2810 fold_convert (long_integer_type_node,
2812 fold_convert (long_integer_type_node, tmp));
2815 /* Upper bound, but not for the last dimension of assumed-size
2817 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
2819 tmp = gfc_conv_array_ubound (se->expr, n);
2820 if (sym->attr.temporary)
2822 gfc_init_se (&tmpse, se);
2823 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
2824 gfc_array_index_type);
2825 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2829 cond = fold_build2_loc (input_location, GT_EXPR,
2830 boolean_type_node, indexse.expr, tmp);
2831 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2832 "above upper bound of %%ld", n+1, sym->name);
2833 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2834 fold_convert (long_integer_type_node,
2836 fold_convert (long_integer_type_node, tmp));
2841 /* Multiply the index by the stride. */
2842 stride = gfc_conv_array_stride (se->expr, n);
2843 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2844 indexse.expr, stride);
2846 /* And add it to the total. */
2847 add_to_offset (&cst_offset, &offset, tmp);
2850 if (!integer_zerop (cst_offset))
2851 offset = fold_build2_loc (input_location, PLUS_EXPR,
2852 gfc_array_index_type, offset, cst_offset);
2854 /* Access the calculated element. */
2855 tmp = gfc_conv_array_data (se->expr);
2856 tmp = build_fold_indirect_ref (tmp);
2857 se->expr = gfc_build_array_ref (tmp, offset, sym->backend_decl);
2861 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
2862 LOOP_DIM dimension (if any) to array's offset. */
2865 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
2866 gfc_array_ref *ar, int array_dim, int loop_dim)
2869 gfc_array_info *info;
2872 info = &ss->info->data.array;
2874 gfc_init_se (&se, NULL);
2876 se.expr = info->descriptor;
2877 stride = gfc_conv_array_stride (info->descriptor, array_dim);
2878 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
2879 gfc_add_block_to_block (pblock, &se.pre);
2881 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
2882 gfc_array_index_type,
2883 info->offset, index);
2884 info->offset = gfc_evaluate_now (info->offset, pblock);
2888 /* Generate the code to be executed immediately before entering a
2889 scalarization loop. */
2892 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2893 stmtblock_t * pblock)
2896 gfc_ss_info *ss_info;
2897 gfc_array_info *info;
2898 gfc_ss_type ss_type;
2903 /* This code will be executed before entering the scalarization loop
2904 for this dimension. */
2905 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2909 if ((ss_info->useflags & flag) == 0)
2912 ss_type = ss_info->type;
2913 if (ss_type != GFC_SS_SECTION
2914 && ss_type != GFC_SS_FUNCTION
2915 && ss_type != GFC_SS_CONSTRUCTOR
2916 && ss_type != GFC_SS_COMPONENT)
2919 info = &ss_info->data.array;
2921 gcc_assert (dim < ss->dimen);
2922 gcc_assert (ss->dimen == loop->dimen);
2925 ar = &info->ref->u.ar;
2929 if (dim == loop->dimen - 1)
2934 /* For the time being, there is no loop reordering. */
2935 gcc_assert (i == loop->order[i]);
2938 if (dim == loop->dimen - 1)
2940 stride = gfc_conv_array_stride (info->descriptor, ss->dim[i]);
2942 /* Calculate the stride of the innermost loop. Hopefully this will
2943 allow the backend optimizers to do their stuff more effectively.
2945 info->stride0 = gfc_evaluate_now (stride, pblock);
2947 /* For the outermost loop calculate the offset due to any
2948 elemental dimensions. It will have been initialized with the
2949 base offset of the array. */
2952 for (i = 0; i < ar->dimen; i++)
2954 if (ar->dimen_type[i] != DIMEN_ELEMENT)
2957 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
2962 /* Add the offset for the previous loop dimension. */
2963 add_array_offset (pblock, loop, ss, ar, ss->dim[i], i);
2965 /* Remember this offset for the second loop. */
2966 if (dim == loop->temp_dim - 1)
2967 info->saved_offset = info->offset;
2972 /* Start a scalarized expression. Creates a scope and declares loop
2976 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2982 gcc_assert (!loop->array_parameter);
2984 for (dim = loop->dimen - 1; dim >= 0; dim--)
2986 n = loop->order[dim];
2988 gfc_start_block (&loop->code[n]);
2990 /* Create the loop variable. */
2991 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2993 if (dim < loop->temp_dim)
2997 /* Calculate values that will be constant within this loop. */
2998 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3000 gfc_start_block (pbody);
3004 /* Generates the actual loop code for a scalarization loop. */
3007 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3008 stmtblock_t * pbody)
3019 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
3020 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3021 && n == loop->dimen - 1)
3023 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3024 init = make_tree_vec (1);
3025 cond = make_tree_vec (1);
3026 incr = make_tree_vec (1);
3028 /* Cycle statement is implemented with a goto. Exit statement must not
3029 be present for this loop. */
3030 exit_label = gfc_build_label_decl (NULL_TREE);
3031 TREE_USED (exit_label) = 1;
3033 /* Label for cycle statements (if needed). */
3034 tmp = build1_v (LABEL_EXPR, exit_label);
3035 gfc_add_expr_to_block (pbody, tmp);
3037 stmt = make_node (OMP_FOR);
3039 TREE_TYPE (stmt) = void_type_node;
3040 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3042 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3043 OMP_CLAUSE_SCHEDULE);
3044 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3045 = OMP_CLAUSE_SCHEDULE_STATIC;
3046 if (ompws_flags & OMPWS_NOWAIT)
3047 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3048 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3050 /* Initialize the loopvar. */
3051 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3053 OMP_FOR_INIT (stmt) = init;
3054 /* The exit condition. */
3055 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3057 loop->loopvar[n], loop->to[n]);
3058 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3059 OMP_FOR_COND (stmt) = cond;
3060 /* Increment the loopvar. */
3061 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3062 loop->loopvar[n], gfc_index_one_node);
3063 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3064 void_type_node, loop->loopvar[n], tmp);
3065 OMP_FOR_INCR (stmt) = incr;
3067 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3068 gfc_add_expr_to_block (&loop->code[n], stmt);
3072 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3073 && (loop->temp_ss == NULL);
3075 loopbody = gfc_finish_block (pbody);
3079 tmp = loop->from[n];
3080 loop->from[n] = loop->to[n];
3084 /* Initialize the loopvar. */
3085 if (loop->loopvar[n] != loop->from[n])
3086 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3088 exit_label = gfc_build_label_decl (NULL_TREE);
3090 /* Generate the loop body. */
3091 gfc_init_block (&block);
3093 /* The exit condition. */
3094 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3095 boolean_type_node, loop->loopvar[n], loop->to[n]);
3096 tmp = build1_v (GOTO_EXPR, exit_label);
3097 TREE_USED (exit_label) = 1;
3098 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3099 gfc_add_expr_to_block (&block, tmp);
3101 /* The main body. */
3102 gfc_add_expr_to_block (&block, loopbody);
3104 /* Increment the loopvar. */
3105 tmp = fold_build2_loc (input_location,
3106 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3107 gfc_array_index_type, loop->loopvar[n],
3108 gfc_index_one_node);
3110 gfc_add_modify (&block, loop->loopvar[n], tmp);
3112 /* Build the loop. */
3113 tmp = gfc_finish_block (&block);
3114 tmp = build1_v (LOOP_EXPR, tmp);
3115 gfc_add_expr_to_block (&loop->code[n], tmp);
3117 /* Add the exit label. */
3118 tmp = build1_v (LABEL_EXPR, exit_label);
3119 gfc_add_expr_to_block (&loop->code[n], tmp);
3125 /* Finishes and generates the loops for a scalarized expression. */
3128 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3133 stmtblock_t *pblock;
3137 /* Generate the loops. */
3138 for (dim = 0; dim < loop->dimen; dim++)
3140 n = loop->order[dim];
3141 gfc_trans_scalarized_loop_end (loop, n, pblock);
3142 loop->loopvar[n] = NULL_TREE;
3143 pblock = &loop->code[n];
3146 tmp = gfc_finish_block (pblock);
3147 gfc_add_expr_to_block (&loop->pre, tmp);
3149 /* Clear all the used flags. */
3150 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3151 ss->info->useflags = 0;
3155 /* Finish the main body of a scalarized expression, and start the secondary
3159 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
3163 stmtblock_t *pblock;
3167 /* We finish as many loops as are used by the temporary. */
3168 for (dim = 0; dim < loop->temp_dim - 1; dim++)
3170 n = loop->order[dim];
3171 gfc_trans_scalarized_loop_end (loop, n, pblock);
3172 loop->loopvar[n] = NULL_TREE;
3173 pblock = &loop->code[n];
3176 /* We don't want to finish the outermost loop entirely. */
3177 n = loop->order[loop->temp_dim - 1];
3178 gfc_trans_scalarized_loop_end (loop, n, pblock);
3180 /* Restore the initial offsets. */
3181 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3183 gfc_ss_type ss_type;
3184 gfc_ss_info *ss_info;
3188 if ((ss_info->useflags & 2) == 0)
3191 ss_type = ss_info->type;
3192 if (ss_type != GFC_SS_SECTION
3193 && ss_type != GFC_SS_FUNCTION
3194 && ss_type != GFC_SS_CONSTRUCTOR
3195 && ss_type != GFC_SS_COMPONENT)
3198 ss_info->data.array.offset = ss_info->data.array.saved_offset;
3201 /* Restart all the inner loops we just finished. */
3202 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
3204 n = loop->order[dim];
3206 gfc_start_block (&loop->code[n]);
3208 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
3210 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
3213 /* Start a block for the secondary copying code. */
3214 gfc_start_block (body);
3218 /* Precalculate (either lower or upper) bound of an array section.
3219 BLOCK: Block in which the (pre)calculation code will go.
3220 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
3221 VALUES[DIM]: Specified bound (NULL <=> unspecified).
3222 DESC: Array descriptor from which the bound will be picked if unspecified
3223 (either lower or upper bound according to LBOUND). */
3226 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
3227 tree desc, int dim, bool lbound)
3230 gfc_expr * input_val = values[dim];
3231 tree *output = &bounds[dim];
3236 /* Specified section bound. */
3237 gfc_init_se (&se, NULL);
3238 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
3239 gfc_add_block_to_block (block, &se.pre);
3244 /* No specific bound specified so use the bound of the array. */
3245 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
3246 gfc_conv_array_ubound (desc, dim);
3248 *output = gfc_evaluate_now (*output, block);
3252 /* Calculate the lower bound of an array section. */
3255 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
3257 gfc_expr *stride = NULL;
3260 gfc_array_info *info;
3263 gcc_assert (ss->info->type == GFC_SS_SECTION);
3265 info = &ss->info->data.array;
3266 ar = &info->ref->u.ar;
3268 if (ar->dimen_type[dim] == DIMEN_VECTOR)
3270 /* We use a zero-based index to access the vector. */
3271 info->start[dim] = gfc_index_zero_node;
3272 info->end[dim] = NULL;
3273 info->stride[dim] = gfc_index_one_node;
3277 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
3278 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
3279 desc = info->descriptor;
3280 stride = ar->stride[dim];
3282 /* Calculate the start of the range. For vector subscripts this will
3283 be the range of the vector. */
3284 evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true);
3286 /* Similarly calculate the end. Although this is not used in the
3287 scalarizer, it is needed when checking bounds and where the end
3288 is an expression with side-effects. */
3289 evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false);
3291 /* Calculate the stride. */
3293 info->stride[dim] = gfc_index_one_node;
3296 gfc_init_se (&se, NULL);
3297 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3298 gfc_add_block_to_block (&loop->pre, &se.pre);
3299 info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre);
3304 /* Calculates the range start and stride for a SS chain. Also gets the
3305 descriptor and data pointer. The range of vector subscripts is the size
3306 of the vector. Array bounds are also checked. */
3309 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3317 /* Determine the rank of the loop. */
3318 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3320 switch (ss->info->type)
3322 case GFC_SS_SECTION:
3323 case GFC_SS_CONSTRUCTOR:
3324 case GFC_SS_FUNCTION:
3325 case GFC_SS_COMPONENT:
3326 loop->dimen = ss->dimen;
3329 /* As usual, lbound and ubound are exceptions!. */
3330 case GFC_SS_INTRINSIC:
3331 switch (ss->info->expr->value.function.isym->id)
3333 case GFC_ISYM_LBOUND:
3334 case GFC_ISYM_UBOUND:
3335 case GFC_ISYM_LCOBOUND:
3336 case GFC_ISYM_UCOBOUND:
3337 case GFC_ISYM_THIS_IMAGE:
3338 loop->dimen = ss->dimen;
3350 /* We should have determined the rank of the expression by now. If
3351 not, that's bad news. */
3355 /* Loop over all the SS in the chain. */
3356 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3358 gfc_ss_info *ss_info;
3359 gfc_array_info *info;
3363 expr = ss_info->expr;
3364 info = &ss_info->data.array;
3366 if (expr && expr->shape && !info->shape)
3367 info->shape = expr->shape;
3369 switch (ss_info->type)
3371 case GFC_SS_SECTION:
3372 /* Get the descriptor for the array. */
3373 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
3375 for (n = 0; n < ss->dimen; n++)
3376 gfc_conv_section_startstride (loop, ss, ss->dim[n]);
3379 case GFC_SS_INTRINSIC:
3380 switch (expr->value.function.isym->id)
3382 /* Fall through to supply start and stride. */
3383 case GFC_ISYM_LBOUND:
3384 case GFC_ISYM_UBOUND:
3385 case GFC_ISYM_LCOBOUND:
3386 case GFC_ISYM_UCOBOUND:
3387 case GFC_ISYM_THIS_IMAGE:
3394 case GFC_SS_CONSTRUCTOR:
3395 case GFC_SS_FUNCTION:
3396 for (n = 0; n < ss->dimen; n++)
3398 int dim = ss->dim[n];
3400 info->start[dim] = gfc_index_zero_node;
3401 info->end[dim] = gfc_index_zero_node;
3402 info->stride[dim] = gfc_index_one_node;
3411 /* The rest is just runtime bound checking. */
3412 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3415 tree lbound, ubound;
3417 tree size[GFC_MAX_DIMENSIONS];
3418 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
3419 gfc_array_info *info;
3423 gfc_start_block (&block);
3425 for (n = 0; n < loop->dimen; n++)
3426 size[n] = NULL_TREE;
3428 for (ss = loop->ss; ss != gfc_ss_terminator;&nbs