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 have just changed the loop bounds, we must clear the
906 corresponding specloop, so that delta calculation is not skipped
907 later in set_delta. */
908 loop->specloop[n] = NULL;
910 /* We are constructing the temporary's descriptor based on the loop
911 dimensions. As the dimensions may be accessed in arbitrary order
912 (think of transpose) the size taken from the n'th loop may not map
913 to the n'th dimension of the array. We need to reconstruct loop infos
914 in the right order before using it to set the descriptor
916 tmp_dim = get_array_ref_dim (ss, n);
917 from[tmp_dim] = loop->from[n];
918 to[tmp_dim] = loop->to[n];
920 info->delta[dim] = gfc_index_zero_node;
921 info->start[dim] = gfc_index_zero_node;
922 info->end[dim] = gfc_index_zero_node;
923 info->stride[dim] = gfc_index_one_node;
926 /* Initialize the descriptor. */
928 gfc_get_array_type_bounds (eltype, ss->dimen, 0, from, to, 1,
929 GFC_ARRAY_UNKNOWN, true);
930 desc = gfc_create_var (type, "atmp");
931 GFC_DECL_PACKED_ARRAY (desc) = 1;
933 info->descriptor = desc;
934 size = gfc_index_one_node;
936 /* Fill in the array dtype. */
937 tmp = gfc_conv_descriptor_dtype (desc);
938 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
941 Fill in the bounds and stride. This is a packed array, so:
944 for (n = 0; n < rank; n++)
947 delta = ubound[n] + 1 - lbound[n];
950 size = size * sizeof(element);
955 /* If there is at least one null loop->to[n], it is a callee allocated
957 for (n = 0; n < loop->dimen; n++)
958 if (loop->to[n] == NULL_TREE)
964 for (n = 0; n < loop->dimen; n++)
968 if (size == NULL_TREE)
970 /* For a callee allocated array express the loop bounds in terms
971 of the descriptor fields. */
972 tmp = fold_build2_loc (input_location,
973 MINUS_EXPR, gfc_array_index_type,
974 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
975 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
980 /* Store the stride and bound components in the descriptor. */
981 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
983 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
984 gfc_index_zero_node);
986 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n],
989 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
990 to[n], gfc_index_one_node);
992 /* Check whether the size for this dimension is negative. */
993 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, tmp,
994 gfc_index_zero_node);
995 cond = gfc_evaluate_now (cond, pre);
1000 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1001 boolean_type_node, or_expr, cond);
1003 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1005 size = gfc_evaluate_now (size, pre);
1008 /* Get the size of the array. */
1010 if (size && !callee_alloc)
1012 /* If or_expr is true, then the extent in at least one
1013 dimension is zero and the size is set to zero. */
1014 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1015 or_expr, gfc_index_zero_node, size);
1018 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1020 fold_convert (gfc_array_index_type,
1021 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
1029 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1032 if (ss->dimen > loop->temp_dim)
1033 loop->temp_dim = ss->dimen;
1039 /* Return the number of iterations in a loop that starts at START,
1040 ends at END, and has step STEP. */
1043 gfc_get_iteration_count (tree start, tree end, tree step)
1048 type = TREE_TYPE (step);
1049 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1050 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1051 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1052 build_int_cst (type, 1));
1053 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1054 build_int_cst (type, 0));
1055 return fold_convert (gfc_array_index_type, tmp);
1059 /* Extend the data in array DESC by EXTRA elements. */
1062 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1069 if (integer_zerop (extra))
1072 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1074 /* Add EXTRA to the upper bound. */
1075 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1077 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1079 /* Get the value of the current data pointer. */
1080 arg0 = gfc_conv_descriptor_data_get (desc);
1082 /* Calculate the new array size. */
1083 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1084 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1085 ubound, gfc_index_one_node);
1086 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1087 fold_convert (size_type_node, tmp),
1088 fold_convert (size_type_node, size));
1090 /* Call the realloc() function. */
1091 tmp = gfc_call_realloc (pblock, arg0, arg1);
1092 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1096 /* Return true if the bounds of iterator I can only be determined
1100 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1102 return (i->start->expr_type != EXPR_CONSTANT
1103 || i->end->expr_type != EXPR_CONSTANT
1104 || i->step->expr_type != EXPR_CONSTANT);
1108 /* Split the size of constructor element EXPR into the sum of two terms,
1109 one of which can be determined at compile time and one of which must
1110 be calculated at run time. Set *SIZE to the former and return true
1111 if the latter might be nonzero. */
1114 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1116 if (expr->expr_type == EXPR_ARRAY)
1117 return gfc_get_array_constructor_size (size, expr->value.constructor);
1118 else if (expr->rank > 0)
1120 /* Calculate everything at run time. */
1121 mpz_set_ui (*size, 0);
1126 /* A single element. */
1127 mpz_set_ui (*size, 1);
1133 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1134 of array constructor C. */
1137 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1145 mpz_set_ui (*size, 0);
1150 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1153 if (i && gfc_iterator_has_dynamic_bounds (i))
1157 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1160 /* Multiply the static part of the element size by the
1161 number of iterations. */
1162 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1163 mpz_fdiv_q (val, val, i->step->value.integer);
1164 mpz_add_ui (val, val, 1);
1165 if (mpz_sgn (val) > 0)
1166 mpz_mul (len, len, val);
1168 mpz_set_ui (len, 0);
1170 mpz_add (*size, *size, len);
1179 /* Make sure offset is a variable. */
1182 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1185 /* We should have already created the offset variable. We cannot
1186 create it here because we may be in an inner scope. */
1187 gcc_assert (*offsetvar != NULL_TREE);
1188 gfc_add_modify (pblock, *offsetvar, *poffset);
1189 *poffset = *offsetvar;
1190 TREE_USED (*offsetvar) = 1;
1194 /* Variables needed for bounds-checking. */
1195 static bool first_len;
1196 static tree first_len_val;
1197 static bool typespec_chararray_ctor;
1200 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1201 tree offset, gfc_se * se, gfc_expr * expr)
1205 gfc_conv_expr (se, expr);
1207 /* Store the value. */
1208 tmp = build_fold_indirect_ref_loc (input_location,
1209 gfc_conv_descriptor_data_get (desc));
1210 tmp = gfc_build_array_ref (tmp, offset, NULL);
1212 if (expr->ts.type == BT_CHARACTER)
1214 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1217 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1218 esize = fold_convert (gfc_charlen_type_node, esize);
1219 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1220 gfc_charlen_type_node, esize,
1221 build_int_cst (gfc_charlen_type_node,
1222 gfc_character_kinds[i].bit_size / 8));
1224 gfc_conv_string_parameter (se);
1225 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1227 /* The temporary is an array of pointers. */
1228 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1229 gfc_add_modify (&se->pre, tmp, se->expr);
1233 /* The temporary is an array of string values. */
1234 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1235 /* We know the temporary and the value will be the same length,
1236 so can use memcpy. */
1237 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1238 se->string_length, se->expr, expr->ts.kind);
1240 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1244 gfc_add_modify (&se->pre, first_len_val,
1250 /* Verify that all constructor elements are of the same
1252 tree cond = fold_build2_loc (input_location, NE_EXPR,
1253 boolean_type_node, first_len_val,
1255 gfc_trans_runtime_check
1256 (true, false, cond, &se->pre, &expr->where,
1257 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1258 fold_convert (long_integer_type_node, first_len_val),
1259 fold_convert (long_integer_type_node, se->string_length));
1265 /* TODO: Should the frontend already have done this conversion? */
1266 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1267 gfc_add_modify (&se->pre, tmp, se->expr);
1270 gfc_add_block_to_block (pblock, &se->pre);
1271 gfc_add_block_to_block (pblock, &se->post);
1275 /* Add the contents of an array to the constructor. DYNAMIC is as for
1276 gfc_trans_array_constructor_value. */
1279 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1280 tree type ATTRIBUTE_UNUSED,
1281 tree desc, gfc_expr * expr,
1282 tree * poffset, tree * offsetvar,
1293 /* We need this to be a variable so we can increment it. */
1294 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1296 gfc_init_se (&se, NULL);
1298 /* Walk the array expression. */
1299 ss = gfc_walk_expr (expr);
1300 gcc_assert (ss != gfc_ss_terminator);
1302 /* Initialize the scalarizer. */
1303 gfc_init_loopinfo (&loop);
1304 gfc_add_ss_to_loop (&loop, ss);
1306 /* Initialize the loop. */
1307 gfc_conv_ss_startstride (&loop);
1308 gfc_conv_loop_setup (&loop, &expr->where);
1310 /* Make sure the constructed array has room for the new data. */
1313 /* Set SIZE to the total number of elements in the subarray. */
1314 size = gfc_index_one_node;
1315 for (n = 0; n < loop.dimen; n++)
1317 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1318 gfc_index_one_node);
1319 size = fold_build2_loc (input_location, MULT_EXPR,
1320 gfc_array_index_type, size, tmp);
1323 /* Grow the constructed array by SIZE elements. */
1324 gfc_grow_array (&loop.pre, desc, size);
1327 /* Make the loop body. */
1328 gfc_mark_ss_chain_used (ss, 1);
1329 gfc_start_scalarized_body (&loop, &body);
1330 gfc_copy_loopinfo_to_se (&se, &loop);
1333 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1334 gcc_assert (se.ss == gfc_ss_terminator);
1336 /* Increment the offset. */
1337 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1338 *poffset, gfc_index_one_node);
1339 gfc_add_modify (&body, *poffset, tmp);
1341 /* Finish the loop. */
1342 gfc_trans_scalarizing_loops (&loop, &body);
1343 gfc_add_block_to_block (&loop.pre, &loop.post);
1344 tmp = gfc_finish_block (&loop.pre);
1345 gfc_add_expr_to_block (pblock, tmp);
1347 gfc_cleanup_loop (&loop);
1351 /* Assign the values to the elements of an array constructor. DYNAMIC
1352 is true if descriptor DESC only contains enough data for the static
1353 size calculated by gfc_get_array_constructor_size. When true, memory
1354 for the dynamic parts must be allocated using realloc. */
1357 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1358 tree desc, gfc_constructor_base base,
1359 tree * poffset, tree * offsetvar,
1368 tree shadow_loopvar = NULL_TREE;
1369 gfc_saved_var saved_loopvar;
1372 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1374 /* If this is an iterator or an array, the offset must be a variable. */
1375 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1376 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1378 /* Shadowing the iterator avoids changing its value and saves us from
1379 keeping track of it. Further, it makes sure that there's always a
1380 backend-decl for the symbol, even if there wasn't one before,
1381 e.g. in the case of an iterator that appears in a specification
1382 expression in an interface mapping. */
1385 gfc_symbol *sym = c->iterator->var->symtree->n.sym;
1386 tree type = gfc_typenode_for_spec (&sym->ts);
1388 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1389 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1392 gfc_start_block (&body);
1394 if (c->expr->expr_type == EXPR_ARRAY)
1396 /* Array constructors can be nested. */
1397 gfc_trans_array_constructor_value (&body, type, desc,
1398 c->expr->value.constructor,
1399 poffset, offsetvar, dynamic);
1401 else if (c->expr->rank > 0)
1403 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1404 poffset, offsetvar, dynamic);
1408 /* This code really upsets the gimplifier so don't bother for now. */
1415 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1417 p = gfc_constructor_next (p);
1422 /* Scalar values. */
1423 gfc_init_se (&se, NULL);
1424 gfc_trans_array_ctor_element (&body, desc, *poffset,
1427 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1428 gfc_array_index_type,
1429 *poffset, gfc_index_one_node);
1433 /* Collect multiple scalar constants into a constructor. */
1434 VEC(constructor_elt,gc) *v = NULL;
1438 HOST_WIDE_INT idx = 0;
1441 /* Count the number of consecutive scalar constants. */
1442 while (p && !(p->iterator
1443 || p->expr->expr_type != EXPR_CONSTANT))
1445 gfc_init_se (&se, NULL);
1446 gfc_conv_constant (&se, p->expr);
1448 if (c->expr->ts.type != BT_CHARACTER)
1449 se.expr = fold_convert (type, se.expr);
1450 /* For constant character array constructors we build
1451 an array of pointers. */
1452 else if (POINTER_TYPE_P (type))
1453 se.expr = gfc_build_addr_expr
1454 (gfc_get_pchar_type (p->expr->ts.kind),
1457 CONSTRUCTOR_APPEND_ELT (v,
1458 build_int_cst (gfc_array_index_type,
1462 p = gfc_constructor_next (p);
1465 bound = size_int (n - 1);
1466 /* Create an array type to hold them. */
1467 tmptype = build_range_type (gfc_array_index_type,
1468 gfc_index_zero_node, bound);
1469 tmptype = build_array_type (type, tmptype);
1471 init = build_constructor (tmptype, v);
1472 TREE_CONSTANT (init) = 1;
1473 TREE_STATIC (init) = 1;
1474 /* Create a static variable to hold the data. */
1475 tmp = gfc_create_var (tmptype, "data");
1476 TREE_STATIC (tmp) = 1;
1477 TREE_CONSTANT (tmp) = 1;
1478 TREE_READONLY (tmp) = 1;
1479 DECL_INITIAL (tmp) = init;
1482 /* Use BUILTIN_MEMCPY to assign the values. */
1483 tmp = gfc_conv_descriptor_data_get (desc);
1484 tmp = build_fold_indirect_ref_loc (input_location,
1486 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1487 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1488 init = gfc_build_addr_expr (NULL_TREE, init);
1490 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1491 bound = build_int_cst (size_type_node, n * size);
1492 tmp = build_call_expr_loc (input_location,
1493 builtin_decl_explicit (BUILT_IN_MEMCPY),
1494 3, tmp, init, bound);
1495 gfc_add_expr_to_block (&body, tmp);
1497 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1498 gfc_array_index_type, *poffset,
1499 build_int_cst (gfc_array_index_type, n));
1501 if (!INTEGER_CST_P (*poffset))
1503 gfc_add_modify (&body, *offsetvar, *poffset);
1504 *poffset = *offsetvar;
1508 /* The frontend should already have done any expansions
1512 /* Pass the code as is. */
1513 tmp = gfc_finish_block (&body);
1514 gfc_add_expr_to_block (pblock, tmp);
1518 /* Build the implied do-loop. */
1519 stmtblock_t implied_do_block;
1527 loopbody = gfc_finish_block (&body);
1529 /* Create a new block that holds the implied-do loop. A temporary
1530 loop-variable is used. */
1531 gfc_start_block(&implied_do_block);
1533 /* Initialize the loop. */
1534 gfc_init_se (&se, NULL);
1535 gfc_conv_expr_val (&se, c->iterator->start);
1536 gfc_add_block_to_block (&implied_do_block, &se.pre);
1537 gfc_add_modify (&implied_do_block, shadow_loopvar, se.expr);
1539 gfc_init_se (&se, NULL);
1540 gfc_conv_expr_val (&se, c->iterator->end);
1541 gfc_add_block_to_block (&implied_do_block, &se.pre);
1542 end = gfc_evaluate_now (se.expr, &implied_do_block);
1544 gfc_init_se (&se, NULL);
1545 gfc_conv_expr_val (&se, c->iterator->step);
1546 gfc_add_block_to_block (&implied_do_block, &se.pre);
1547 step = gfc_evaluate_now (se.expr, &implied_do_block);
1549 /* If this array expands dynamically, and the number of iterations
1550 is not constant, we won't have allocated space for the static
1551 part of C->EXPR's size. Do that now. */
1552 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1554 /* Get the number of iterations. */
1555 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1557 /* Get the static part of C->EXPR's size. */
1558 gfc_get_array_constructor_element_size (&size, c->expr);
1559 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1561 /* Grow the array by TMP * TMP2 elements. */
1562 tmp = fold_build2_loc (input_location, MULT_EXPR,
1563 gfc_array_index_type, tmp, tmp2);
1564 gfc_grow_array (&implied_do_block, desc, tmp);
1567 /* Generate the loop body. */
1568 exit_label = gfc_build_label_decl (NULL_TREE);
1569 gfc_start_block (&body);
1571 /* Generate the exit condition. Depending on the sign of
1572 the step variable we have to generate the correct
1574 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1575 step, build_int_cst (TREE_TYPE (step), 0));
1576 cond = fold_build3_loc (input_location, COND_EXPR,
1577 boolean_type_node, tmp,
1578 fold_build2_loc (input_location, GT_EXPR,
1579 boolean_type_node, shadow_loopvar, end),
1580 fold_build2_loc (input_location, LT_EXPR,
1581 boolean_type_node, shadow_loopvar, end));
1582 tmp = build1_v (GOTO_EXPR, exit_label);
1583 TREE_USED (exit_label) = 1;
1584 tmp = build3_v (COND_EXPR, cond, tmp,
1585 build_empty_stmt (input_location));
1586 gfc_add_expr_to_block (&body, tmp);
1588 /* The main loop body. */
1589 gfc_add_expr_to_block (&body, loopbody);
1591 /* Increase loop variable by step. */
1592 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1593 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1595 gfc_add_modify (&body, shadow_loopvar, tmp);
1597 /* Finish the loop. */
1598 tmp = gfc_finish_block (&body);
1599 tmp = build1_v (LOOP_EXPR, tmp);
1600 gfc_add_expr_to_block (&implied_do_block, tmp);
1602 /* Add the exit label. */
1603 tmp = build1_v (LABEL_EXPR, exit_label);
1604 gfc_add_expr_to_block (&implied_do_block, tmp);
1606 /* Finishe the implied-do loop. */
1607 tmp = gfc_finish_block(&implied_do_block);
1608 gfc_add_expr_to_block(pblock, tmp);
1610 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1617 /* A catch-all to obtain the string length for anything that is not a
1618 a substring of non-constant length, a constant, array or variable. */
1621 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1626 /* Don't bother if we already know the length is a constant. */
1627 if (*len && INTEGER_CST_P (*len))
1630 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1631 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1634 gfc_conv_const_charlen (e->ts.u.cl);
1635 *len = e->ts.u.cl->backend_decl;
1639 /* Otherwise, be brutal even if inefficient. */
1640 ss = gfc_walk_expr (e);
1641 gfc_init_se (&se, NULL);
1643 /* No function call, in case of side effects. */
1644 se.no_function_call = 1;
1645 if (ss == gfc_ss_terminator)
1646 gfc_conv_expr (&se, e);
1648 gfc_conv_expr_descriptor (&se, e, ss);
1650 /* Fix the value. */
1651 *len = gfc_evaluate_now (se.string_length, &se.pre);
1653 gfc_add_block_to_block (block, &se.pre);
1654 gfc_add_block_to_block (block, &se.post);
1656 e->ts.u.cl->backend_decl = *len;
1661 /* Figure out the string length of a variable reference expression.
1662 Used by get_array_ctor_strlen. */
1665 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
1671 /* Don't bother if we already know the length is a constant. */
1672 if (*len && INTEGER_CST_P (*len))
1675 ts = &expr->symtree->n.sym->ts;
1676 for (ref = expr->ref; ref; ref = ref->next)
1681 /* Array references don't change the string length. */
1685 /* Use the length of the component. */
1686 ts = &ref->u.c.component->ts;
1690 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1691 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1693 /* Note that this might evaluate expr. */
1694 get_array_ctor_all_strlen (block, expr, len);
1697 mpz_init_set_ui (char_len, 1);
1698 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1699 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1700 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1701 *len = convert (gfc_charlen_type_node, *len);
1702 mpz_clear (char_len);
1710 *len = ts->u.cl->backend_decl;
1714 /* Figure out the string length of a character array constructor.
1715 If len is NULL, don't calculate the length; this happens for recursive calls
1716 when a sub-array-constructor is an element but not at the first position,
1717 so when we're not interested in the length.
1718 Returns TRUE if all elements are character constants. */
1721 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
1728 if (gfc_constructor_first (base) == NULL)
1731 *len = build_int_cstu (gfc_charlen_type_node, 0);
1735 /* Loop over all constructor elements to find out is_const, but in len we
1736 want to store the length of the first, not the last, element. We can
1737 of course exit the loop as soon as is_const is found to be false. */
1738 for (c = gfc_constructor_first (base);
1739 c && is_const; c = gfc_constructor_next (c))
1741 switch (c->expr->expr_type)
1744 if (len && !(*len && INTEGER_CST_P (*len)))
1745 *len = build_int_cstu (gfc_charlen_type_node,
1746 c->expr->value.character.length);
1750 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1757 get_array_ctor_var_strlen (block, c->expr, len);
1763 get_array_ctor_all_strlen (block, c->expr, len);
1767 /* After the first iteration, we don't want the length modified. */
1774 /* Check whether the array constructor C consists entirely of constant
1775 elements, and if so returns the number of those elements, otherwise
1776 return zero. Note, an empty or NULL array constructor returns zero. */
1778 unsigned HOST_WIDE_INT
1779 gfc_constant_array_constructor_p (gfc_constructor_base base)
1781 unsigned HOST_WIDE_INT nelem = 0;
1783 gfc_constructor *c = gfc_constructor_first (base);
1787 || c->expr->rank > 0
1788 || c->expr->expr_type != EXPR_CONSTANT)
1790 c = gfc_constructor_next (c);
1797 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1798 and the tree type of it's elements, TYPE, return a static constant
1799 variable that is compile-time initialized. */
1802 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1804 tree tmptype, init, tmp;
1805 HOST_WIDE_INT nelem;
1810 VEC(constructor_elt,gc) *v = NULL;
1812 /* First traverse the constructor list, converting the constants
1813 to tree to build an initializer. */
1815 c = gfc_constructor_first (expr->value.constructor);
1818 gfc_init_se (&se, NULL);
1819 gfc_conv_constant (&se, c->expr);
1820 if (c->expr->ts.type != BT_CHARACTER)
1821 se.expr = fold_convert (type, se.expr);
1822 else if (POINTER_TYPE_P (type))
1823 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
1825 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
1827 c = gfc_constructor_next (c);
1831 /* Next determine the tree type for the array. We use the gfortran
1832 front-end's gfc_get_nodesc_array_type in order to create a suitable
1833 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1835 memset (&as, 0, sizeof (gfc_array_spec));
1837 as.rank = expr->rank;
1838 as.type = AS_EXPLICIT;
1841 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1842 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
1846 for (i = 0; i < expr->rank; i++)
1848 int tmp = (int) mpz_get_si (expr->shape[i]);
1849 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1850 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
1854 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
1856 /* as is not needed anymore. */
1857 for (i = 0; i < as.rank + as.corank; i++)
1859 gfc_free_expr (as.lower[i]);
1860 gfc_free_expr (as.upper[i]);
1863 init = build_constructor (tmptype, v);
1865 TREE_CONSTANT (init) = 1;
1866 TREE_STATIC (init) = 1;
1868 tmp = gfc_create_var (tmptype, "A");
1869 TREE_STATIC (tmp) = 1;
1870 TREE_CONSTANT (tmp) = 1;
1871 TREE_READONLY (tmp) = 1;
1872 DECL_INITIAL (tmp) = init;
1878 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1879 This mostly initializes the scalarizer state info structure with the
1880 appropriate values to directly use the array created by the function
1881 gfc_build_constant_array_constructor. */
1884 trans_constant_array_constructor (gfc_ss * ss, tree type)
1886 gfc_array_info *info;
1890 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
1892 info = &ss->info->data.array;
1894 info->descriptor = tmp;
1895 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
1896 info->offset = gfc_index_zero_node;
1898 for (i = 0; i < ss->dimen; i++)
1900 info->delta[i] = gfc_index_zero_node;
1901 info->start[i] = gfc_index_zero_node;
1902 info->end[i] = gfc_index_zero_node;
1903 info->stride[i] = gfc_index_one_node;
1907 /* Helper routine of gfc_trans_array_constructor to determine if the
1908 bounds of the loop specified by LOOP are constant and simple enough
1909 to use with trans_constant_array_constructor. Returns the
1910 iteration count of the loop if suitable, and NULL_TREE otherwise. */
1913 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1915 tree size = gfc_index_one_node;
1919 for (i = 0; i < loop->dimen; i++)
1921 /* If the bounds aren't constant, return NULL_TREE. */
1922 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1924 if (!integer_zerop (loop->from[i]))
1926 /* Only allow nonzero "from" in one-dimensional arrays. */
1927 if (loop->dimen != 1)
1929 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1930 gfc_array_index_type,
1931 loop->to[i], loop->from[i]);
1935 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1936 tmp, gfc_index_one_node);
1937 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1945 /* Array constructors are handled by constructing a temporary, then using that
1946 within the scalarization loop. This is not optimal, but seems by far the
1950 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
1952 gfc_constructor_base c;
1959 bool old_first_len, old_typespec_chararray_ctor;
1960 tree old_first_len_val;
1961 gfc_ss_info *ss_info;
1964 /* Save the old values for nested checking. */
1965 old_first_len = first_len;
1966 old_first_len_val = first_len_val;
1967 old_typespec_chararray_ctor = typespec_chararray_ctor;
1970 expr = ss_info->expr;
1972 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
1973 typespec was given for the array constructor. */
1974 typespec_chararray_ctor = (expr->ts.u.cl
1975 && expr->ts.u.cl->length_from_typespec);
1977 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1978 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
1980 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1984 gcc_assert (ss->dimen == loop->dimen);
1986 c = expr->value.constructor;
1987 if (expr->ts.type == BT_CHARACTER)
1991 /* get_array_ctor_strlen walks the elements of the constructor, if a
1992 typespec was given, we already know the string length and want the one
1994 if (typespec_chararray_ctor && expr->ts.u.cl->length
1995 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
1999 const_string = false;
2000 gfc_init_se (&length_se, NULL);
2001 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2002 gfc_charlen_type_node);
2003 ss_info->string_length = length_se.expr;
2004 gfc_add_block_to_block (&loop->pre, &length_se.pre);
2005 gfc_add_block_to_block (&loop->post, &length_se.post);
2008 const_string = get_array_ctor_strlen (&loop->pre, c,
2009 &ss_info->string_length);
2011 /* Complex character array constructors should have been taken care of
2012 and not end up here. */
2013 gcc_assert (ss_info->string_length);
2015 expr->ts.u.cl->backend_decl = ss_info->string_length;
2017 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2019 type = build_pointer_type (type);
2022 type = gfc_typenode_for_spec (&expr->ts);
2024 /* See if the constructor determines the loop bounds. */
2027 if (expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
2029 /* We have a multidimensional parameter. */
2031 for (n = 0; n < expr->rank; n++)
2033 loop->from[n] = gfc_index_zero_node;
2034 loop->to[n] = gfc_conv_mpz_to_tree (expr->shape [n],
2035 gfc_index_integer_kind);
2036 loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2037 gfc_array_index_type,
2038 loop->to[n], gfc_index_one_node);
2042 if (loop->to[0] == NULL_TREE)
2046 /* We should have a 1-dimensional, zero-based loop. */
2047 gcc_assert (loop->dimen == 1);
2048 gcc_assert (integer_zerop (loop->from[0]));
2050 /* Split the constructor size into a static part and a dynamic part.
2051 Allocate the static size up-front and record whether the dynamic
2052 size might be nonzero. */
2054 dynamic = gfc_get_array_constructor_size (&size, c);
2055 mpz_sub_ui (size, size, 1);
2056 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2060 /* Special case constant array constructors. */
2063 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2066 tree size = constant_array_constructor_loop_size (loop);
2067 if (size && compare_tree_int (size, nelem) == 0)
2069 trans_constant_array_constructor (ss, type);
2075 if (TREE_CODE (loop->to[0]) == VAR_DECL)
2078 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, ss,
2079 type, NULL_TREE, dynamic, true, false, where);
2081 desc = ss_info->data.array.descriptor;
2082 offset = gfc_index_zero_node;
2083 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2084 TREE_NO_WARNING (offsetvar) = 1;
2085 TREE_USED (offsetvar) = 0;
2086 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
2087 &offset, &offsetvar, dynamic);
2089 /* If the array grows dynamically, the upper bound of the loop variable
2090 is determined by the array's final upper bound. */
2093 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2094 gfc_array_index_type,
2095 offsetvar, gfc_index_one_node);
2096 tmp = gfc_evaluate_now (tmp, &loop->pre);
2097 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2098 if (loop->to[0] && TREE_CODE (loop->to[0]) == VAR_DECL)
2099 gfc_add_modify (&loop->pre, loop->to[0], tmp);
2104 if (TREE_USED (offsetvar))
2105 pushdecl (offsetvar);
2107 gcc_assert (INTEGER_CST_P (offset));
2110 /* Disable bound checking for now because it's probably broken. */
2111 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2118 /* Restore old values of globals. */
2119 first_len = old_first_len;
2120 first_len_val = old_first_len_val;
2121 typespec_chararray_ctor = old_typespec_chararray_ctor;
2125 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2126 called after evaluating all of INFO's vector dimensions. Go through
2127 each such vector dimension and see if we can now fill in any missing
2131 set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss * ss)
2133 gfc_array_info *info;
2141 info = &ss->info->data.array;
2143 for (n = 0; n < loop->dimen; n++)
2146 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
2147 && loop->to[n] == NULL)
2149 /* Loop variable N indexes vector dimension DIM, and we don't
2150 yet know the upper bound of loop variable N. Set it to the
2151 difference between the vector's upper and lower bounds. */
2152 gcc_assert (loop->from[n] == gfc_index_zero_node);
2153 gcc_assert (info->subscript[dim]
2154 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2156 gfc_init_se (&se, NULL);
2157 desc = info->subscript[dim]->info->data.array.descriptor;
2158 zero = gfc_rank_cst[0];
2159 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2160 gfc_array_index_type,
2161 gfc_conv_descriptor_ubound_get (desc, zero),
2162 gfc_conv_descriptor_lbound_get (desc, zero));
2163 tmp = gfc_evaluate_now (tmp, &loop->pre);
2170 /* Add the pre and post chains for all the scalar expressions in a SS chain
2171 to loop. This is called after the loop parameters have been calculated,
2172 but before the actual scalarizing loops. */
2175 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2179 gfc_ss_info *ss_info;
2180 gfc_array_info *info;
2184 /* TODO: This can generate bad code if there are ordering dependencies,
2185 e.g., a callee allocated function and an unknown size constructor. */
2186 gcc_assert (ss != NULL);
2188 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2193 expr = ss_info->expr;
2194 info = &ss_info->data.array;
2196 switch (ss_info->type)
2199 /* Scalar expression. Evaluate this now. This includes elemental
2200 dimension indices, but not array section bounds. */
2201 gfc_init_se (&se, NULL);
2202 gfc_conv_expr (&se, expr);
2203 gfc_add_block_to_block (&loop->pre, &se.pre);
2205 if (expr->ts.type != BT_CHARACTER)
2207 /* Move the evaluation of scalar expressions outside the
2208 scalarization loop, except for WHERE assignments. */
2210 se.expr = convert(gfc_array_index_type, se.expr);
2211 if (!ss_info->where)
2212 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
2213 gfc_add_block_to_block (&loop->pre, &se.post);
2216 gfc_add_block_to_block (&loop->post, &se.post);
2218 ss_info->data.scalar.value = se.expr;
2219 ss_info->string_length = se.string_length;
2222 case GFC_SS_REFERENCE:
2223 /* Scalar argument to elemental procedure. Evaluate this
2225 gfc_init_se (&se, NULL);
2226 gfc_conv_expr (&se, expr);
2227 gfc_add_block_to_block (&loop->pre, &se.pre);
2228 gfc_add_block_to_block (&loop->post, &se.post);
2230 ss_info->data.scalar.value = gfc_evaluate_now (se.expr, &loop->pre);
2231 ss_info->string_length = se.string_length;
2234 case GFC_SS_SECTION:
2235 /* Add the expressions for scalar and vector subscripts. */
2236 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2237 if (info->subscript[n])
2238 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2240 set_vector_loop_bounds (loop, ss);
2244 /* Get the vector's descriptor and store it in SS. */
2245 gfc_init_se (&se, NULL);
2246 gfc_conv_expr_descriptor (&se, expr, gfc_walk_expr (expr));
2247 gfc_add_block_to_block (&loop->pre, &se.pre);
2248 gfc_add_block_to_block (&loop->post, &se.post);
2249 info->descriptor = se.expr;
2252 case GFC_SS_INTRINSIC:
2253 gfc_add_intrinsic_ss_code (loop, ss);
2256 case GFC_SS_FUNCTION:
2257 /* Array function return value. We call the function and save its
2258 result in a temporary for use inside the loop. */
2259 gfc_init_se (&se, NULL);
2262 gfc_conv_expr (&se, expr);
2263 gfc_add_block_to_block (&loop->pre, &se.pre);
2264 gfc_add_block_to_block (&loop->post, &se.post);
2265 ss_info->string_length = se.string_length;
2268 case GFC_SS_CONSTRUCTOR:
2269 if (expr->ts.type == BT_CHARACTER
2270 && ss_info->string_length == NULL
2272 && expr->ts.u.cl->length)
2274 gfc_init_se (&se, NULL);
2275 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2276 gfc_charlen_type_node);
2277 ss_info->string_length = se.expr;
2278 gfc_add_block_to_block (&loop->pre, &se.pre);
2279 gfc_add_block_to_block (&loop->post, &se.post);
2281 gfc_trans_array_constructor (loop, ss, where);
2285 case GFC_SS_COMPONENT:
2286 /* Do nothing. These are handled elsewhere. */
2296 /* Translate expressions for the descriptor and data pointer of a SS. */
2300 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2303 gfc_ss_info *ss_info;
2304 gfc_array_info *info;
2308 info = &ss_info->data.array;
2310 /* Get the descriptor for the array to be scalarized. */
2311 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2312 gfc_init_se (&se, NULL);
2313 se.descriptor_only = 1;
2314 gfc_conv_expr_lhs (&se, ss_info->expr);
2315 gfc_add_block_to_block (block, &se.pre);
2316 info->descriptor = se.expr;
2317 ss_info->string_length = se.string_length;
2321 /* Also the data pointer. */
2322 tmp = gfc_conv_array_data (se.expr);
2323 /* If this is a variable or address of a variable we use it directly.
2324 Otherwise we must evaluate it now to avoid breaking dependency
2325 analysis by pulling the expressions for elemental array indices
2328 || (TREE_CODE (tmp) == ADDR_EXPR
2329 && DECL_P (TREE_OPERAND (tmp, 0)))))
2330 tmp = gfc_evaluate_now (tmp, block);
2333 tmp = gfc_conv_array_offset (se.expr);
2334 info->offset = gfc_evaluate_now (tmp, block);
2336 /* Make absolutely sure that the saved_offset is indeed saved
2337 so that the variable is still accessible after the loops
2339 info->saved_offset = info->offset;
2344 /* Initialize a gfc_loopinfo structure. */
2347 gfc_init_loopinfo (gfc_loopinfo * loop)
2351 memset (loop, 0, sizeof (gfc_loopinfo));
2352 gfc_init_block (&loop->pre);
2353 gfc_init_block (&loop->post);
2355 /* Initially scalarize in order and default to no loop reversal. */
2356 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2359 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2362 loop->ss = gfc_ss_terminator;
2366 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2370 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2376 /* Return an expression for the data pointer of an array. */
2379 gfc_conv_array_data (tree descriptor)
2383 type = TREE_TYPE (descriptor);
2384 if (GFC_ARRAY_TYPE_P (type))
2386 if (TREE_CODE (type) == POINTER_TYPE)
2390 /* Descriptorless arrays. */
2391 return gfc_build_addr_expr (NULL_TREE, descriptor);
2395 return gfc_conv_descriptor_data_get (descriptor);
2399 /* Return an expression for the base offset of an array. */
2402 gfc_conv_array_offset (tree descriptor)
2406 type = TREE_TYPE (descriptor);
2407 if (GFC_ARRAY_TYPE_P (type))
2408 return GFC_TYPE_ARRAY_OFFSET (type);
2410 return gfc_conv_descriptor_offset_get (descriptor);
2414 /* Get an expression for the array stride. */
2417 gfc_conv_array_stride (tree descriptor, int dim)
2422 type = TREE_TYPE (descriptor);
2424 /* For descriptorless arrays use the array size. */
2425 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2426 if (tmp != NULL_TREE)
2429 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2434 /* Like gfc_conv_array_stride, but for the lower bound. */
2437 gfc_conv_array_lbound (tree descriptor, int dim)
2442 type = TREE_TYPE (descriptor);
2444 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2445 if (tmp != NULL_TREE)
2448 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2453 /* Like gfc_conv_array_stride, but for the upper bound. */
2456 gfc_conv_array_ubound (tree descriptor, int dim)
2461 type = TREE_TYPE (descriptor);
2463 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2464 if (tmp != NULL_TREE)
2467 /* This should only ever happen when passing an assumed shape array
2468 as an actual parameter. The value will never be used. */
2469 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2470 return gfc_index_zero_node;
2472 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2477 /* Generate code to perform an array index bound check. */
2480 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
2481 locus * where, bool check_upper)
2484 tree tmp_lo, tmp_up;
2487 const char * name = NULL;
2489 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2492 descriptor = ss->info->data.array.descriptor;
2494 index = gfc_evaluate_now (index, &se->pre);
2496 /* We find a name for the error message. */
2497 name = ss->info->expr->symtree->n.sym->name;
2498 gcc_assert (name != NULL);
2500 if (TREE_CODE (descriptor) == VAR_DECL)
2501 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
2503 /* If upper bound is present, include both bounds in the error message. */
2506 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2507 tmp_up = gfc_conv_array_ubound (descriptor, n);
2510 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2511 "outside of expected range (%%ld:%%ld)", n+1, name);
2513 asprintf (&msg, "Index '%%ld' of dimension %d "
2514 "outside of expected range (%%ld:%%ld)", n+1);
2516 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2518 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2519 fold_convert (long_integer_type_node, index),
2520 fold_convert (long_integer_type_node, tmp_lo),
2521 fold_convert (long_integer_type_node, tmp_up));
2522 fault = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2524 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2525 fold_convert (long_integer_type_node, index),
2526 fold_convert (long_integer_type_node, tmp_lo),
2527 fold_convert (long_integer_type_node, tmp_up));
2532 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2535 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2536 "below lower bound of %%ld", n+1, name);
2538 asprintf (&msg, "Index '%%ld' of dimension %d "
2539 "below lower bound of %%ld", n+1);
2541 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2543 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2544 fold_convert (long_integer_type_node, index),
2545 fold_convert (long_integer_type_node, tmp_lo));
2553 /* Return the offset for an index. Performs bound checking for elemental
2554 dimensions. Single element references are processed separately.
2555 DIM is the array dimension, I is the loop dimension. */
2558 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
2559 gfc_array_ref * ar, tree stride)
2561 gfc_array_info *info;
2566 info = &ss->info->data.array;
2568 /* Get the index into the array for this dimension. */
2571 gcc_assert (ar->type != AR_ELEMENT);
2572 switch (ar->dimen_type[dim])
2574 case DIMEN_THIS_IMAGE:
2578 /* Elemental dimension. */
2579 gcc_assert (info->subscript[dim]
2580 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
2581 /* We've already translated this value outside the loop. */
2582 index = info->subscript[dim]->info->data.scalar.value;
2584 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2585 ar->as->type != AS_ASSUMED_SIZE
2586 || dim < ar->dimen - 1);
2590 gcc_assert (info && se->loop);
2591 gcc_assert (info->subscript[dim]
2592 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2593 desc = info->subscript[dim]->info->data.array.descriptor;
2595 /* Get a zero-based index into the vector. */
2596 index = fold_build2_loc (input_location, MINUS_EXPR,
2597 gfc_array_index_type,
2598 se->loop->loopvar[i], se->loop->from[i]);
2600 /* Multiply the index by the stride. */
2601 index = fold_build2_loc (input_location, MULT_EXPR,
2602 gfc_array_index_type,
2603 index, gfc_conv_array_stride (desc, 0));
2605 /* Read the vector to get an index into info->descriptor. */
2606 data = build_fold_indirect_ref_loc (input_location,
2607 gfc_conv_array_data (desc));
2608 index = gfc_build_array_ref (data, index, NULL);
2609 index = gfc_evaluate_now (index, &se->pre);
2610 index = fold_convert (gfc_array_index_type, index);
2612 /* Do any bounds checking on the final info->descriptor index. */
2613 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2614 ar->as->type != AS_ASSUMED_SIZE
2615 || dim < ar->dimen - 1);
2619 /* Scalarized dimension. */
2620 gcc_assert (info && se->loop);
2622 /* Multiply the loop variable by the stride and delta. */
2623 index = se->loop->loopvar[i];
2624 if (!integer_onep (info->stride[dim]))
2625 index = fold_build2_loc (input_location, MULT_EXPR,
2626 gfc_array_index_type, index,
2628 if (!integer_zerop (info->delta[dim]))
2629 index = fold_build2_loc (input_location, PLUS_EXPR,
2630 gfc_array_index_type, index,
2640 /* Temporary array or derived type component. */
2641 gcc_assert (se->loop);
2642 index = se->loop->loopvar[se->loop->order[i]];
2644 /* Pointer functions can have stride[0] different from unity.
2645 Use the stride returned by the function call and stored in
2646 the descriptor for the temporary. */
2647 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
2648 && se->ss->info->expr
2649 && se->ss->info->expr->symtree
2650 && se->ss->info->expr->symtree->n.sym->result
2651 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
2652 stride = gfc_conv_descriptor_stride_get (info->descriptor,
2655 if (!integer_zerop (info->delta[dim]))
2656 index = fold_build2_loc (input_location, PLUS_EXPR,
2657 gfc_array_index_type, index, info->delta[dim]);
2660 /* Multiply by the stride. */
2661 if (!integer_onep (stride))
2662 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2669 /* Build a scalarized reference to an array. */
2672 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2674 gfc_array_info *info;
2675 tree decl = NULL_TREE;
2683 expr = ss->info->expr;
2684 info = &ss->info->data.array;
2686 n = se->loop->order[0];
2690 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
2691 /* Add the offset for this dimension to the stored offset for all other
2693 if (!integer_zerop (info->offset))
2694 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2695 index, info->offset);
2697 if (expr && is_subref_array (expr))
2698 decl = expr->symtree->n.sym->backend_decl;
2700 tmp = build_fold_indirect_ref_loc (input_location, info->data);
2701 se->expr = gfc_build_array_ref (tmp, index, decl);
2705 /* Translate access of temporary array. */
2708 gfc_conv_tmp_array_ref (gfc_se * se)
2710 se->string_length = se->ss->info->string_length;
2711 gfc_conv_scalarized_array_ref (se, NULL);
2712 gfc_advance_se_ss_chain (se);
2715 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
2718 add_to_offset (tree *cst_offset, tree *offset, tree t)
2720 if (TREE_CODE (t) == INTEGER_CST)
2721 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
2724 if (!integer_zerop (*offset))
2725 *offset = fold_build2_loc (input_location, PLUS_EXPR,
2726 gfc_array_index_type, *offset, t);
2732 /* Build an array reference. se->expr already holds the array descriptor.
2733 This should be either a variable, indirect variable reference or component
2734 reference. For arrays which do not have a descriptor, se->expr will be
2736 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2739 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2743 tree offset, cst_offset;
2751 gcc_assert (ar->codimen);
2753 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
2754 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
2757 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
2758 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
2759 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
2761 /* Use the actual tree type and not the wrapped coarray. */
2762 if (!se->want_pointer)
2763 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
2770 /* Handle scalarized references separately. */
2771 if (ar->type != AR_ELEMENT)
2773 gfc_conv_scalarized_array_ref (se, ar);
2774 gfc_advance_se_ss_chain (se);
2778 cst_offset = offset = gfc_index_zero_node;
2779 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
2781 /* Calculate the offsets from all the dimensions. Make sure to associate
2782 the final offset so that we form a chain of loop invariant summands. */
2783 for (n = ar->dimen - 1; n >= 0; n--)
2785 /* Calculate the index for this dimension. */
2786 gfc_init_se (&indexse, se);
2787 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2788 gfc_add_block_to_block (&se->pre, &indexse.pre);
2790 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2792 /* Check array bounds. */
2796 /* Evaluate the indexse.expr only once. */
2797 indexse.expr = save_expr (indexse.expr);
2800 tmp = gfc_conv_array_lbound (se->expr, n);
2801 if (sym->attr.temporary)
2803 gfc_init_se (&tmpse, se);
2804 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
2805 gfc_array_index_type);
2806 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2810 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2812 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2813 "below lower bound of %%ld", n+1, sym->name);
2814 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2815 fold_convert (long_integer_type_node,
2817 fold_convert (long_integer_type_node, tmp));
2820 /* Upper bound, but not for the last dimension of assumed-size
2822 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
2824 tmp = gfc_conv_array_ubound (se->expr, n);
2825 if (sym->attr.temporary)
2827 gfc_init_se (&tmpse, se);
2828 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
2829 gfc_array_index_type);
2830 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2834 cond = fold_build2_loc (input_location, GT_EXPR,
2835 boolean_type_node, indexse.expr, tmp);
2836 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2837 "above upper bound of %%ld", n+1, sym->name);
2838 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2839 fold_convert (long_integer_type_node,
2841 fold_convert (long_integer_type_node, tmp));
2846 /* Multiply the index by the stride. */
2847 stride = gfc_conv_array_stride (se->expr, n);
2848 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2849 indexse.expr, stride);
2851 /* And add it to the total. */
2852 add_to_offset (&cst_offset, &offset, tmp);
2855 if (!integer_zerop (cst_offset))
2856 offset = fold_build2_loc (input_location, PLUS_EXPR,
2857 gfc_array_index_type, offset, cst_offset);
2859 /* Access the calculated element. */
2860 tmp = gfc_conv_array_data (se->expr);
2861 tmp = build_fold_indirect_ref (tmp);
2862 se->expr = gfc_build_array_ref (tmp, offset, sym->backend_decl);
2866 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
2867 LOOP_DIM dimension (if any) to array's offset. */
2870 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
2871 gfc_array_ref *ar, int array_dim, int loop_dim)
2874 gfc_array_info *info;
2877 info = &ss->info->data.array;
2879 gfc_init_se (&se, NULL);
2881 se.expr = info->descriptor;
2882 stride = gfc_conv_array_stride (info->descriptor, array_dim);
2883 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
2884 gfc_add_block_to_block (pblock, &se.pre);
2886 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
2887 gfc_array_index_type,
2888 info->offset, index);
2889 info->offset = gfc_evaluate_now (info->offset, pblock);
2893 /* Generate the code to be executed immediately before entering a
2894 scalarization loop. */
2897 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2898 stmtblock_t * pblock)
2901 gfc_ss_info *ss_info;
2902 gfc_array_info *info;
2903 gfc_ss_type ss_type;
2908 /* This code will be executed before entering the scalarization loop
2909 for this dimension. */
2910 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2914 if ((ss_info->useflags & flag) == 0)
2917 ss_type = ss_info->type;
2918 if (ss_type != GFC_SS_SECTION
2919 && ss_type != GFC_SS_FUNCTION
2920 && ss_type != GFC_SS_CONSTRUCTOR
2921 && ss_type != GFC_SS_COMPONENT)
2924 info = &ss_info->data.array;
2926 gcc_assert (dim < ss->dimen);
2927 gcc_assert (ss->dimen == loop->dimen);
2930 ar = &info->ref->u.ar;
2934 if (dim == loop->dimen - 1)
2939 /* For the time being, there is no loop reordering. */
2940 gcc_assert (i == loop->order[i]);
2943 if (dim == loop->dimen - 1)
2945 stride = gfc_conv_array_stride (info->descriptor, ss->dim[i]);
2947 /* Calculate the stride of the innermost loop. Hopefully this will
2948 allow the backend optimizers to do their stuff more effectively.
2950 info->stride0 = gfc_evaluate_now (stride, pblock);
2952 /* For the outermost loop calculate the offset due to any
2953 elemental dimensions. It will have been initialized with the
2954 base offset of the array. */
2957 for (i = 0; i < ar->dimen; i++)
2959 if (ar->dimen_type[i] != DIMEN_ELEMENT)
2962 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
2967 /* Add the offset for the previous loop dimension. */
2968 add_array_offset (pblock, loop, ss, ar, ss->dim[i], i);
2970 /* Remember this offset for the second loop. */
2971 if (dim == loop->temp_dim - 1)
2972 info->saved_offset = info->offset;
2977 /* Start a scalarized expression. Creates a scope and declares loop
2981 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2987 gcc_assert (!loop->array_parameter);
2989 for (dim = loop->dimen - 1; dim >= 0; dim--)
2991 n = loop->order[dim];
2993 gfc_start_block (&loop->code[n]);
2995 /* Create the loop variable. */
2996 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2998 if (dim < loop->temp_dim)
3002 /* Calculate values that will be constant within this loop. */
3003 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3005 gfc_start_block (pbody);
3009 /* Generates the actual loop code for a scalarization loop. */
3012 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3013 stmtblock_t * pbody)
3024 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
3025 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3026 && n == loop->dimen - 1)
3028 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3029 init = make_tree_vec (1);
3030 cond = make_tree_vec (1);
3031 incr = make_tree_vec (1);
3033 /* Cycle statement is implemented with a goto. Exit statement must not
3034 be present for this loop. */
3035 exit_label = gfc_build_label_decl (NULL_TREE);
3036 TREE_USED (exit_label) = 1;
3038 /* Label for cycle statements (if needed). */
3039 tmp = build1_v (LABEL_EXPR, exit_label);
3040 gfc_add_expr_to_block (pbody, tmp);
3042 stmt = make_node (OMP_FOR);
3044 TREE_TYPE (stmt) = void_type_node;
3045 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3047 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3048 OMP_CLAUSE_SCHEDULE);
3049 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3050 = OMP_CLAUSE_SCHEDULE_STATIC;
3051 if (ompws_flags & OMPWS_NOWAIT)
3052 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3053 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3055 /* Initialize the loopvar. */
3056 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3058 OMP_FOR_INIT (stmt) = init;
3059 /* The exit condition. */
3060 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3062 loop->loopvar[n], loop->to[n]);
3063 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3064 OMP_FOR_COND (stmt) = cond;
3065 /* Increment the loopvar. */
3066 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3067 loop->loopvar[n], gfc_index_one_node);
3068 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3069 void_type_node, loop->loopvar[n], tmp);
3070 OMP_FOR_INCR (stmt) = incr;
3072 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3073 gfc_add_expr_to_block (&loop->code[n], stmt);
3077 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3078 && (loop->temp_ss == NULL);
3080 loopbody = gfc_finish_block (pbody);
3084 tmp = loop->from[n];
3085 loop->from[n] = loop->to[n];
3089 /* Initialize the loopvar. */
3090 if (loop->loopvar[n] != loop->from[n])
3091 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3093 exit_label = gfc_build_label_decl (NULL_TREE);
3095 /* Generate the loop body. */
3096 gfc_init_block (&block);
3098 /* The exit condition. */
3099 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3100 boolean_type_node, loop->loopvar[n], loop->to[n]);
3101 tmp = build1_v (GOTO_EXPR, exit_label);
3102 TREE_USED (exit_label) = 1;
3103 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3104 gfc_add_expr_to_block (&block, tmp);
3106 /* The main body. */
3107 gfc_add_expr_to_block (&block, loopbody);
3109 /* Increment the loopvar. */
3110 tmp = fold_build2_loc (input_location,
3111 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3112 gfc_array_index_type, loop->loopvar[n],
3113 gfc_index_one_node);
3115 gfc_add_modify (&block, loop->loopvar[n], tmp);
3117 /* Build the loop. */
3118 tmp = gfc_finish_block (&block);
3119 tmp = build1_v (LOOP_EXPR, tmp);
3120 gfc_add_expr_to_block (&loop->code[n], tmp);
3122 /* Add the exit label. */
3123 tmp = build1_v (LABEL_EXPR, exit_label);
3124 gfc_add_expr_to_block (&loop->code[n], tmp);
3130 /* Finishes and generates the loops for a scalarized expression. */
3133 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3138 stmtblock_t *pblock;
3142 /* Generate the loops. */
3143 for (dim = 0; dim < loop->dimen; dim++)
3145 n = loop->order[dim];
3146 gfc_trans_scalarized_loop_end (loop, n, pblock);
3147 loop->loopvar[n] = NULL_TREE;
3148 pblock = &loop->code[n];
3151 tmp = gfc_finish_block (pblock);
3152 gfc_add_expr_to_block (&loop->pre, tmp);
3154 /* Clear all the used flags. */
3155 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3156 ss->info->useflags = 0;
3160 /* Finish the main body of a scalarized expression, and start the secondary
3164 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
3168 stmtblock_t *pblock;
3172 /* We finish as many loops as are used by the temporary. */
3173 for (dim = 0; dim < loop->temp_dim - 1; dim++)
3175 n = loop->order[dim];
3176 gfc_trans_scalarized_loop_end (loop, n, pblock);
3177 loop->loopvar[n] = NULL_TREE;
3178 pblock = &loop->code[n];
3181 /* We don't want to finish the outermost loop entirely. */
3182 n = loop->order[loop->temp_dim - 1];
3183 gfc_trans_scalarized_loop_end (loop, n, pblock);
3185 /* Restore the initial offsets. */
3186 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3188 gfc_ss_type ss_type;
3189 gfc_ss_info *ss_info;
3193 if ((ss_info->useflags & 2) == 0)
3196 ss_type = ss_info->type;
3197 if (ss_type != GFC_SS_SECTION
3198 && ss_type != GFC_SS_FUNCTION
3199 && ss_type != GFC_SS_CONSTRUCTOR
3200 && ss_type != GFC_SS_COMPONENT)
3203 ss_info->data.array.offset = ss_info->data.array.saved_offset;
3206 /* Restart all the inner loops we just finished. */
3207 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
3209 n = loop->order[dim];
3211 gfc_start_block (&loop->code[n]);
3213 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
3215 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
3218 /* Start a block for the secondary copying code. */
3219 gfc_start_block (body);
3223 /* Precalculate (either lower or upper) bound of an array section.
3224 BLOCK: Block in which the (pre)calculation code will go.
3225 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
3226 VALUES[DIM]: Specified bound (NULL <=> unspecified).
3227 DESC: Array descriptor from which the bound will be picked if unspecified
3228 (either lower or upper bound according to LBOUND). */
3231 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
3232 tree desc, int dim, bool lbound)
3235 gfc_expr * input_val = values[dim];
3236 tree *output = &bounds[dim];
3241 /* Specified section bound. */
3242 gfc_init_se (&se, NULL);
3243 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
3244 gfc_add_block_to_block (block, &se.pre);
3249 /* No specific bound specified so use the bound of the array. */
3250 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
3251 gfc_conv_array_ubound (desc, dim);
3253 *output = gfc_evaluate_now (*output, block);
3257 /* Calculate the lower bound of an array section. */
3260 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
3262 gfc_expr *stride = NULL;
3265 gfc_array_info *info;
3268 gcc_assert (ss->info->type == GFC_SS_SECTION);
3270 info = &ss->info->data.array;
3271 ar = &info->ref->u.ar;
3273 if (ar->dimen_type[dim] == DIMEN_VECTOR)
3275 /* We use a zero-based index to access the vector. */
3276 info->start[dim] = gfc_index_zero_node;
3277 info->end[dim] = NULL;
3278 info->stride[dim] = gfc_index_one_node;
3282 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
3283 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
3284 desc = info->descriptor;
3285 stride = ar->stride[dim];
3287 /* Calculate the start of the range. For vector subscripts this will
3288 be the range of the vector. */
3289 evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true);
3291 /* Similarly calculate the end. Although this is not used in the
3292 scalarizer, it is needed when checking bounds and where the end
3293 is an expression with side-effects. */
3294 evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false);
3296 /* Calculate the stride. */
3298 info->stride[dim] = gfc_index_one_node;
3301 gfc_init_se (&se, NULL);
3302 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3303 gfc_add_block_to_block (&loop->pre, &se.pre);
3304 info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre);
3309 /* Calculates the range start and stride for a SS chain. Also gets the
3310 descriptor and data pointer. The range of vector subscripts is the size
3311 of the vector. Array bounds are also checked. */
3314 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3322 /* Determine the rank of the loop. */
3323 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3325 switch (ss->info->type)
3327 case GFC_SS_SECTION:
3328 case GFC_SS_CONSTRUCTOR:
3329 case GFC_SS_FUNCTION:
3330 case GFC_SS_COMPONENT:
3331 loop->dimen = ss->dimen;
3334 /* As usual, lbound and ubound are exceptions!. */
3335 case GFC_SS_INTRINSIC:
3336 switch (ss->info->expr->value.function.isym->id)
3338 case GFC_ISYM_LBOUND:
3339 case GFC_ISYM_UBOUND:
3340 case GFC_ISYM_LCOBOUND:
3341 case GFC_ISYM_UCOBOUND:
3342 case GFC_ISYM_THIS_IMAGE:
3343 loop->dimen = ss->dimen;
3355 /* We should have determined the rank of the expression by now. If
3356 not, that's bad news. */
3360 /* Loop over all the SS in the chain. */
3361 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3363 gfc_ss_info *ss_info;
3364 gfc_array_info *info;
3368 expr = ss_info->expr;
3369 info = &ss_info->data.array;
3371 if (expr && expr->shape && !info->shape)
3372 info->shape = expr->shape;
3374 switch (ss_info->type)
3376 case GFC_SS_SECTION:
3377 /* Get the descriptor for the array. */
3378 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
3380 for (n = 0; n < ss->dimen; n++)
3381 gfc_conv_section_startstride (loop, ss, ss->dim[n]);
3384 case GFC_SS_INTRINSIC:
3385 switch (expr->value.function.isym->id)
3387 /* Fall through to supply start and stride. */
3388 case GFC_ISYM_LBOUND:
3389 case GFC_ISYM_UBOUND:
3390 case GFC_ISYM_LCOBOUND:
3391 case GFC_ISYM_UCOBOUND:
3392 case GFC_ISYM_THIS_IMAGE:
3399 case GFC_SS_CONSTRUCTOR:
3400 case GFC_SS_FUNCTION:
3401 for (n = 0; n < ss->dimen; n++)
3403 int dim = ss->dim[n];
3405 info->start[dim] = gfc_index_zero_node;
3406 info->end[dim] = gfc_index_zero_node;
3407 info->stride[dim] = gfc_index_one_node;
3416 /* The rest is just runtime bound checking. */
3417 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3420 tree lbound, ubound;
3422 tree size[GFC_MAX_DIMENSIONS];
3423 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
3424 gfc_array_info *info;