* varasm.c (bss_initializer_p): Remove static.
[official-gcc.git] / gcc / fortran / trans-array.c
blob068989203690a1f73dc4a6fd91843661cd085f41
1 /* Array translation routines
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011, 2012
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
13 version.
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
18 for more details.
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
29 expressions.
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
55 term is calculated.
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. */
80 #include "config.h"
81 #include "system.h"
82 #include "coretypes.h"
83 #include "tree.h"
84 #include "gimple.h" /* For create_tmp_var_name. */
85 #include "diagnostic-core.h" /* For internal_error/fatal_error. */
86 #include "flags.h"
87 #include "gfortran.h"
88 #include "constructor.h"
89 #include "trans.h"
90 #include "trans-stmt.h"
91 #include "trans-types.h"
92 #include "trans-array.h"
93 #include "trans-const.h"
94 #include "dependency.h"
96 static 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;
103 static tree
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! */
128 #define DATA_FIELD 0
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. */
141 tree
142 gfc_conv_descriptor_data_get (tree desc)
144 tree field, type, t;
146 type = TREE_TYPE (desc);
147 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
149 field = TYPE_FIELDS (type);
150 gcc_assert (DATA_FIELD == 0);
152 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
153 field, NULL_TREE);
154 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
156 return 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. */
167 void
168 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
170 tree field, type, t;
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,
179 field, NULL_TREE);
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. */
187 tree
188 gfc_conv_descriptor_data_addr (tree desc)
190 tree field, type, t;
192 type = TREE_TYPE (desc);
193 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
195 field = TYPE_FIELDS (type);
196 gcc_assert (DATA_FIELD == 0);
198 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
199 field, NULL_TREE);
200 return gfc_build_addr_expr (NULL_TREE, t);
203 static tree
204 gfc_conv_descriptor_offset (tree desc)
206 tree type;
207 tree field;
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);
219 tree
220 gfc_conv_descriptor_offset_get (tree desc)
222 return gfc_conv_descriptor_offset (desc);
225 void
226 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
227 tree value)
229 tree t = gfc_conv_descriptor_offset (desc);
230 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
234 tree
235 gfc_conv_descriptor_dtype (tree desc)
237 tree field;
238 tree type;
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 tree
252 gfc_conv_descriptor_rank (tree desc)
254 tree tmp;
255 tree dtype;
257 dtype = gfc_conv_descriptor_dtype (desc);
258 tmp = build_int_cst (TREE_TYPE (dtype), GFC_DTYPE_RANK_MASK);
259 tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (dtype),
260 dtype, tmp);
261 return fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
265 tree
266 gfc_get_descriptor_dimension (tree desc)
268 tree type, field;
270 type = TREE_TYPE (desc);
271 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
273 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
274 gcc_assert (field != NULL_TREE
275 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
276 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
278 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
279 desc, field, NULL_TREE);
283 static tree
284 gfc_conv_descriptor_dimension (tree desc, tree dim)
286 tree tmp;
288 tmp = gfc_get_descriptor_dimension (desc);
290 return gfc_build_array_ref (tmp, dim, NULL);
294 tree
295 gfc_conv_descriptor_token (tree desc)
297 tree type;
298 tree field;
300 type = TREE_TYPE (desc);
301 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
302 gcc_assert (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE);
303 gcc_assert (gfc_option.coarray == GFC_FCOARRAY_LIB);
304 field = gfc_advance_chain (TYPE_FIELDS (type), CAF_TOKEN_FIELD);
305 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == prvoid_type_node);
307 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
308 desc, field, NULL_TREE);
312 static tree
313 gfc_conv_descriptor_stride (tree desc, tree dim)
315 tree tmp;
316 tree field;
318 tmp = gfc_conv_descriptor_dimension (desc, dim);
319 field = TYPE_FIELDS (TREE_TYPE (tmp));
320 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
321 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
323 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
324 tmp, field, NULL_TREE);
325 return tmp;
328 tree
329 gfc_conv_descriptor_stride_get (tree desc, tree dim)
331 tree type = TREE_TYPE (desc);
332 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
333 if (integer_zerop (dim)
334 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
335 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
336 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
337 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
338 return gfc_index_one_node;
340 return gfc_conv_descriptor_stride (desc, dim);
343 void
344 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
345 tree dim, tree value)
347 tree t = gfc_conv_descriptor_stride (desc, dim);
348 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
351 static tree
352 gfc_conv_descriptor_lbound (tree desc, tree dim)
354 tree tmp;
355 tree field;
357 tmp = gfc_conv_descriptor_dimension (desc, dim);
358 field = TYPE_FIELDS (TREE_TYPE (tmp));
359 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
360 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
362 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
363 tmp, field, NULL_TREE);
364 return tmp;
367 tree
368 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
370 return gfc_conv_descriptor_lbound (desc, dim);
373 void
374 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
375 tree dim, tree value)
377 tree t = gfc_conv_descriptor_lbound (desc, dim);
378 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
381 static tree
382 gfc_conv_descriptor_ubound (tree desc, tree dim)
384 tree tmp;
385 tree field;
387 tmp = gfc_conv_descriptor_dimension (desc, dim);
388 field = TYPE_FIELDS (TREE_TYPE (tmp));
389 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
390 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
392 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
393 tmp, field, NULL_TREE);
394 return tmp;
397 tree
398 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
400 return gfc_conv_descriptor_ubound (desc, dim);
403 void
404 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
405 tree dim, tree value)
407 tree t = gfc_conv_descriptor_ubound (desc, dim);
408 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
411 /* Build a null array descriptor constructor. */
413 tree
414 gfc_build_null_descriptor (tree type)
416 tree field;
417 tree tmp;
419 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
420 gcc_assert (DATA_FIELD == 0);
421 field = TYPE_FIELDS (type);
423 /* Set a NULL data pointer. */
424 tmp = build_constructor_single (type, field, null_pointer_node);
425 TREE_CONSTANT (tmp) = 1;
426 /* All other fields are ignored. */
428 return tmp;
432 /* Modify a descriptor such that the lbound of a given dimension is the value
433 specified. This also updates ubound and offset accordingly. */
435 void
436 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
437 int dim, tree new_lbound)
439 tree offs, ubound, lbound, stride;
440 tree diff, offs_diff;
442 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
444 offs = gfc_conv_descriptor_offset_get (desc);
445 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
446 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
447 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
449 /* Get difference (new - old) by which to shift stuff. */
450 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
451 new_lbound, lbound);
453 /* Shift ubound and offset accordingly. This has to be done before
454 updating the lbound, as they depend on the lbound expression! */
455 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
456 ubound, diff);
457 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
458 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
459 diff, stride);
460 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
461 offs, offs_diff);
462 gfc_conv_descriptor_offset_set (block, desc, offs);
464 /* Finally set lbound to value we want. */
465 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
469 /* Cleanup those #defines. */
471 #undef DATA_FIELD
472 #undef OFFSET_FIELD
473 #undef DTYPE_FIELD
474 #undef DIMENSION_FIELD
475 #undef CAF_TOKEN_FIELD
476 #undef STRIDE_SUBFIELD
477 #undef LBOUND_SUBFIELD
478 #undef UBOUND_SUBFIELD
481 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
482 flags & 1 = Main loop body.
483 flags & 2 = temp copy loop. */
485 void
486 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
488 for (; ss != gfc_ss_terminator; ss = ss->next)
489 ss->info->useflags = flags;
493 /* Free a gfc_ss chain. */
495 void
496 gfc_free_ss_chain (gfc_ss * ss)
498 gfc_ss *next;
500 while (ss != gfc_ss_terminator)
502 gcc_assert (ss != NULL);
503 next = ss->next;
504 gfc_free_ss (ss);
505 ss = next;
510 static void
511 free_ss_info (gfc_ss_info *ss_info)
513 int n;
515 ss_info->refcount--;
516 if (ss_info->refcount > 0)
517 return;
519 gcc_assert (ss_info->refcount == 0);
521 switch (ss_info->type)
523 case GFC_SS_SECTION:
524 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
525 if (ss_info->data.array.subscript[n])
526 gfc_free_ss_chain (ss_info->data.array.subscript[n]);
527 break;
529 default:
530 break;
533 free (ss_info);
537 /* Free a SS. */
539 void
540 gfc_free_ss (gfc_ss * ss)
542 free_ss_info (ss->info);
543 free (ss);
547 /* Creates and initializes an array type gfc_ss struct. */
549 gfc_ss *
550 gfc_get_array_ss (gfc_ss *next, gfc_expr *expr, int dimen, gfc_ss_type type)
552 gfc_ss *ss;
553 gfc_ss_info *ss_info;
554 int i;
556 ss_info = gfc_get_ss_info ();
557 ss_info->refcount++;
558 ss_info->type = type;
559 ss_info->expr = expr;
561 ss = gfc_get_ss ();
562 ss->info = ss_info;
563 ss->next = next;
564 ss->dimen = dimen;
565 for (i = 0; i < ss->dimen; i++)
566 ss->dim[i] = i;
568 return ss;
572 /* Creates and initializes a temporary type gfc_ss struct. */
574 gfc_ss *
575 gfc_get_temp_ss (tree type, tree string_length, int dimen)
577 gfc_ss *ss;
578 gfc_ss_info *ss_info;
579 int i;
581 ss_info = gfc_get_ss_info ();
582 ss_info->refcount++;
583 ss_info->type = GFC_SS_TEMP;
584 ss_info->string_length = string_length;
585 ss_info->data.temp.type = type;
587 ss = gfc_get_ss ();
588 ss->info = ss_info;
589 ss->next = gfc_ss_terminator;
590 ss->dimen = dimen;
591 for (i = 0; i < ss->dimen; i++)
592 ss->dim[i] = i;
594 return ss;
598 /* Creates and initializes a scalar type gfc_ss struct. */
600 gfc_ss *
601 gfc_get_scalar_ss (gfc_ss *next, gfc_expr *expr)
603 gfc_ss *ss;
604 gfc_ss_info *ss_info;
606 ss_info = gfc_get_ss_info ();
607 ss_info->refcount++;
608 ss_info->type = GFC_SS_SCALAR;
609 ss_info->expr = expr;
611 ss = gfc_get_ss ();
612 ss->info = ss_info;
613 ss->next = next;
615 return ss;
619 /* Free all the SS associated with a loop. */
621 void
622 gfc_cleanup_loop (gfc_loopinfo * loop)
624 gfc_loopinfo *loop_next, **ploop;
625 gfc_ss *ss;
626 gfc_ss *next;
628 ss = loop->ss;
629 while (ss != gfc_ss_terminator)
631 gcc_assert (ss != NULL);
632 next = ss->loop_chain;
633 gfc_free_ss (ss);
634 ss = next;
637 /* Remove reference to self in the parent loop. */
638 if (loop->parent)
639 for (ploop = &loop->parent->nested; *ploop; ploop = &(*ploop)->next)
640 if (*ploop == loop)
642 *ploop = loop->next;
643 break;
646 /* Free non-freed nested loops. */
647 for (loop = loop->nested; loop; loop = loop_next)
649 loop_next = loop->next;
650 gfc_cleanup_loop (loop);
651 free (loop);
656 static void
657 set_ss_loop (gfc_ss *ss, gfc_loopinfo *loop)
659 int n;
661 for (; ss != gfc_ss_terminator; ss = ss->next)
663 ss->loop = loop;
665 if (ss->info->type == GFC_SS_SCALAR
666 || ss->info->type == GFC_SS_REFERENCE
667 || ss->info->type == GFC_SS_TEMP)
668 continue;
670 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
671 if (ss->info->data.array.subscript[n] != NULL)
672 set_ss_loop (ss->info->data.array.subscript[n], loop);
677 /* Associate a SS chain with a loop. */
679 void
680 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
682 gfc_ss *ss;
683 gfc_loopinfo *nested_loop;
685 if (head == gfc_ss_terminator)
686 return;
688 set_ss_loop (head, loop);
690 ss = head;
691 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
693 if (ss->nested_ss)
695 nested_loop = ss->nested_ss->loop;
697 /* More than one ss can belong to the same loop. Hence, we add the
698 loop to the chain only if it is different from the previously
699 added one, to avoid duplicate nested loops. */
700 if (nested_loop != loop->nested)
702 gcc_assert (nested_loop->parent == NULL);
703 nested_loop->parent = loop;
705 gcc_assert (nested_loop->next == NULL);
706 nested_loop->next = loop->nested;
707 loop->nested = nested_loop;
709 else
710 gcc_assert (nested_loop->parent == loop);
713 if (ss->next == gfc_ss_terminator)
714 ss->loop_chain = loop->ss;
715 else
716 ss->loop_chain = ss->next;
718 gcc_assert (ss == gfc_ss_terminator);
719 loop->ss = head;
723 /* Generate an initializer for a static pointer or allocatable array. */
725 void
726 gfc_trans_static_array_pointer (gfc_symbol * sym)
728 tree type;
730 gcc_assert (TREE_STATIC (sym->backend_decl));
731 /* Just zero the data member. */
732 type = TREE_TYPE (sym->backend_decl);
733 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
737 /* If the bounds of SE's loop have not yet been set, see if they can be
738 determined from array spec AS, which is the array spec of a called
739 function. MAPPING maps the callee's dummy arguments to the values
740 that the caller is passing. Add any initialization and finalization
741 code to SE. */
743 void
744 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
745 gfc_se * se, gfc_array_spec * as)
747 int n, dim, total_dim;
748 gfc_se tmpse;
749 gfc_ss *ss;
750 tree lower;
751 tree upper;
752 tree tmp;
754 total_dim = 0;
756 if (!as || as->type != AS_EXPLICIT)
757 return;
759 for (ss = se->ss; ss; ss = ss->parent)
761 total_dim += ss->loop->dimen;
762 for (n = 0; n < ss->loop->dimen; n++)
764 /* The bound is known, nothing to do. */
765 if (ss->loop->to[n] != NULL_TREE)
766 continue;
768 dim = ss->dim[n];
769 gcc_assert (dim < as->rank);
770 gcc_assert (ss->loop->dimen <= as->rank);
772 /* Evaluate the lower bound. */
773 gfc_init_se (&tmpse, NULL);
774 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
775 gfc_add_block_to_block (&se->pre, &tmpse.pre);
776 gfc_add_block_to_block (&se->post, &tmpse.post);
777 lower = fold_convert (gfc_array_index_type, tmpse.expr);
779 /* ...and the upper bound. */
780 gfc_init_se (&tmpse, NULL);
781 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
782 gfc_add_block_to_block (&se->pre, &tmpse.pre);
783 gfc_add_block_to_block (&se->post, &tmpse.post);
784 upper = fold_convert (gfc_array_index_type, tmpse.expr);
786 /* Set the upper bound of the loop to UPPER - LOWER. */
787 tmp = fold_build2_loc (input_location, MINUS_EXPR,
788 gfc_array_index_type, upper, lower);
789 tmp = gfc_evaluate_now (tmp, &se->pre);
790 ss->loop->to[n] = tmp;
794 gcc_assert (total_dim == as->rank);
798 /* Generate code to allocate an array temporary, or create a variable to
799 hold the data. If size is NULL, zero the descriptor so that the
800 callee will allocate the array. If DEALLOC is true, also generate code to
801 free the array afterwards.
803 If INITIAL is not NULL, it is packed using internal_pack and the result used
804 as data instead of allocating a fresh, unitialized area of memory.
806 Initialization code is added to PRE and finalization code to POST.
807 DYNAMIC is true if the caller may want to extend the array later
808 using realloc. This prevents us from putting the array on the stack. */
810 static void
811 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
812 gfc_array_info * info, tree size, tree nelem,
813 tree initial, bool dynamic, bool dealloc)
815 tree tmp;
816 tree desc;
817 bool onstack;
819 desc = info->descriptor;
820 info->offset = gfc_index_zero_node;
821 if (size == NULL_TREE || integer_zerop (size))
823 /* A callee allocated array. */
824 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
825 onstack = FALSE;
827 else
829 /* Allocate the temporary. */
830 onstack = !dynamic && initial == NULL_TREE
831 && (gfc_option.flag_stack_arrays
832 || gfc_can_put_var_on_stack (size));
834 if (onstack)
836 /* Make a temporary variable to hold the data. */
837 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
838 nelem, gfc_index_one_node);
839 tmp = gfc_evaluate_now (tmp, pre);
840 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
841 tmp);
842 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
843 tmp);
844 tmp = gfc_create_var (tmp, "A");
845 /* If we're here only because of -fstack-arrays we have to
846 emit a DECL_EXPR to make the gimplifier emit alloca calls. */
847 if (!gfc_can_put_var_on_stack (size))
848 gfc_add_expr_to_block (pre,
849 fold_build1_loc (input_location,
850 DECL_EXPR, TREE_TYPE (tmp),
851 tmp));
852 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
853 gfc_conv_descriptor_data_set (pre, desc, tmp);
855 else
857 /* Allocate memory to hold the data or call internal_pack. */
858 if (initial == NULL_TREE)
860 tmp = gfc_call_malloc (pre, NULL, size);
861 tmp = gfc_evaluate_now (tmp, pre);
863 else
865 tree packed;
866 tree source_data;
867 tree was_packed;
868 stmtblock_t do_copying;
870 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
871 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
872 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
873 tmp = gfc_get_element_type (tmp);
874 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
875 packed = gfc_create_var (build_pointer_type (tmp), "data");
877 tmp = build_call_expr_loc (input_location,
878 gfor_fndecl_in_pack, 1, initial);
879 tmp = fold_convert (TREE_TYPE (packed), tmp);
880 gfc_add_modify (pre, packed, tmp);
882 tmp = build_fold_indirect_ref_loc (input_location,
883 initial);
884 source_data = gfc_conv_descriptor_data_get (tmp);
886 /* internal_pack may return source->data without any allocation
887 or copying if it is already packed. If that's the case, we
888 need to allocate and copy manually. */
890 gfc_start_block (&do_copying);
891 tmp = gfc_call_malloc (&do_copying, NULL, size);
892 tmp = fold_convert (TREE_TYPE (packed), tmp);
893 gfc_add_modify (&do_copying, packed, tmp);
894 tmp = gfc_build_memcpy_call (packed, source_data, size);
895 gfc_add_expr_to_block (&do_copying, tmp);
897 was_packed = fold_build2_loc (input_location, EQ_EXPR,
898 boolean_type_node, packed,
899 source_data);
900 tmp = gfc_finish_block (&do_copying);
901 tmp = build3_v (COND_EXPR, was_packed, tmp,
902 build_empty_stmt (input_location));
903 gfc_add_expr_to_block (pre, tmp);
905 tmp = fold_convert (pvoid_type_node, packed);
908 gfc_conv_descriptor_data_set (pre, desc, tmp);
911 info->data = gfc_conv_descriptor_data_get (desc);
913 /* The offset is zero because we create temporaries with a zero
914 lower bound. */
915 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
917 if (dealloc && !onstack)
919 /* Free the temporary. */
920 tmp = gfc_conv_descriptor_data_get (desc);
921 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
922 gfc_add_expr_to_block (post, tmp);
927 /* Get the scalarizer array dimension corresponding to actual array dimension
928 given by ARRAY_DIM.
930 For example, if SS represents the array ref a(1,:,:,1), it is a
931 bidimensional scalarizer array, and the result would be 0 for ARRAY_DIM=1,
932 and 1 for ARRAY_DIM=2.
933 If SS represents transpose(a(:,1,1,:)), it is again a bidimensional
934 scalarizer array, and the result would be 1 for ARRAY_DIM=0 and 0 for
935 ARRAY_DIM=3.
936 If SS represents sum(a(:,:,:,1), dim=1), it is a 2+1-dimensional scalarizer
937 array. If called on the inner ss, the result would be respectively 0,1,2 for
938 ARRAY_DIM=0,1,2. If called on the outer ss, the result would be 0,1
939 for ARRAY_DIM=1,2. */
941 static int
942 get_scalarizer_dim_for_array_dim (gfc_ss *ss, int array_dim)
944 int array_ref_dim;
945 int n;
947 array_ref_dim = 0;
949 for (; ss; ss = ss->parent)
950 for (n = 0; n < ss->dimen; n++)
951 if (ss->dim[n] < array_dim)
952 array_ref_dim++;
954 return array_ref_dim;
958 static gfc_ss *
959 innermost_ss (gfc_ss *ss)
961 while (ss->nested_ss != NULL)
962 ss = ss->nested_ss;
964 return ss;
969 /* Get the array reference dimension corresponding to the given loop dimension.
970 It is different from the true array dimension given by the dim array in
971 the case of a partial array reference (i.e. a(:,:,1,:) for example)
972 It is different from the loop dimension in the case of a transposed array.
975 static int
976 get_array_ref_dim_for_loop_dim (gfc_ss *ss, int loop_dim)
978 return get_scalarizer_dim_for_array_dim (innermost_ss (ss),
979 ss->dim[loop_dim]);
983 /* Generate code to create and initialize the descriptor for a temporary
984 array. This is used for both temporaries needed by the scalarizer, and
985 functions returning arrays. Adjusts the loop variables to be
986 zero-based, and calculates the loop bounds for callee allocated arrays.
987 Allocate the array unless it's callee allocated (we have a callee
988 allocated array if 'callee_alloc' is true, or if loop->to[n] is
989 NULL_TREE for any n). Also fills in the descriptor, data and offset
990 fields of info if known. Returns the size of the array, or NULL for a
991 callee allocated array.
993 'eltype' == NULL signals that the temporary should be a class object.
994 The 'initial' expression is used to obtain the size of the dynamic
995 type; otherwise the allocation and initialisation proceeds as for any
996 other expression
998 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
999 gfc_trans_allocate_array_storage. */
1001 tree
1002 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
1003 tree eltype, tree initial, bool dynamic,
1004 bool dealloc, bool callee_alloc, locus * where)
1006 gfc_loopinfo *loop;
1007 gfc_ss *s;
1008 gfc_array_info *info;
1009 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
1010 tree type;
1011 tree desc;
1012 tree tmp;
1013 tree size;
1014 tree nelem;
1015 tree cond;
1016 tree or_expr;
1017 tree class_expr = NULL_TREE;
1018 int n, dim, tmp_dim;
1019 int total_dim = 0;
1021 /* This signals a class array for which we need the size of the
1022 dynamic type. Generate an eltype and then the class expression. */
1023 if (eltype == NULL_TREE && initial)
1025 gcc_assert (POINTER_TYPE_P (TREE_TYPE (initial)));
1026 class_expr = build_fold_indirect_ref_loc (input_location, initial);
1027 eltype = TREE_TYPE (class_expr);
1028 eltype = gfc_get_element_type (eltype);
1029 /* Obtain the structure (class) expression. */
1030 class_expr = TREE_OPERAND (class_expr, 0);
1031 gcc_assert (class_expr);
1034 memset (from, 0, sizeof (from));
1035 memset (to, 0, sizeof (to));
1037 info = &ss->info->data.array;
1039 gcc_assert (ss->dimen > 0);
1040 gcc_assert (ss->loop->dimen == ss->dimen);
1042 if (gfc_option.warn_array_temp && where)
1043 gfc_warning ("Creating array temporary at %L", where);
1045 /* Set the lower bound to zero. */
1046 for (s = ss; s; s = s->parent)
1048 loop = s->loop;
1050 total_dim += loop->dimen;
1051 for (n = 0; n < loop->dimen; n++)
1053 dim = s->dim[n];
1055 /* Callee allocated arrays may not have a known bound yet. */
1056 if (loop->to[n])
1057 loop->to[n] = gfc_evaluate_now (
1058 fold_build2_loc (input_location, MINUS_EXPR,
1059 gfc_array_index_type,
1060 loop->to[n], loop->from[n]),
1061 pre);
1062 loop->from[n] = gfc_index_zero_node;
1064 /* We have just changed the loop bounds, we must clear the
1065 corresponding specloop, so that delta calculation is not skipped
1066 later in gfc_set_delta. */
1067 loop->specloop[n] = NULL;
1069 /* We are constructing the temporary's descriptor based on the loop
1070 dimensions. As the dimensions may be accessed in arbitrary order
1071 (think of transpose) the size taken from the n'th loop may not map
1072 to the n'th dimension of the array. We need to reconstruct loop
1073 infos in the right order before using it to set the descriptor
1074 bounds. */
1075 tmp_dim = get_scalarizer_dim_for_array_dim (ss, dim);
1076 from[tmp_dim] = loop->from[n];
1077 to[tmp_dim] = loop->to[n];
1079 info->delta[dim] = gfc_index_zero_node;
1080 info->start[dim] = gfc_index_zero_node;
1081 info->end[dim] = gfc_index_zero_node;
1082 info->stride[dim] = gfc_index_one_node;
1086 /* Initialize the descriptor. */
1087 type =
1088 gfc_get_array_type_bounds (eltype, total_dim, 0, from, to, 1,
1089 GFC_ARRAY_UNKNOWN, true);
1090 desc = gfc_create_var (type, "atmp");
1091 GFC_DECL_PACKED_ARRAY (desc) = 1;
1093 info->descriptor = desc;
1094 size = gfc_index_one_node;
1096 /* Fill in the array dtype. */
1097 tmp = gfc_conv_descriptor_dtype (desc);
1098 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
1101 Fill in the bounds and stride. This is a packed array, so:
1103 size = 1;
1104 for (n = 0; n < rank; n++)
1106 stride[n] = size
1107 delta = ubound[n] + 1 - lbound[n];
1108 size = size * delta;
1110 size = size * sizeof(element);
1113 or_expr = NULL_TREE;
1115 /* If there is at least one null loop->to[n], it is a callee allocated
1116 array. */
1117 for (n = 0; n < total_dim; n++)
1118 if (to[n] == NULL_TREE)
1120 size = NULL_TREE;
1121 break;
1124 if (size == NULL_TREE)
1125 for (s = ss; s; s = s->parent)
1126 for (n = 0; n < s->loop->dimen; n++)
1128 dim = get_scalarizer_dim_for_array_dim (ss, s->dim[n]);
1130 /* For a callee allocated array express the loop bounds in terms
1131 of the descriptor fields. */
1132 tmp = fold_build2_loc (input_location,
1133 MINUS_EXPR, gfc_array_index_type,
1134 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]),
1135 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]));
1136 s->loop->to[n] = tmp;
1138 else
1140 for (n = 0; n < total_dim; n++)
1142 /* Store the stride and bound components in the descriptor. */
1143 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
1145 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
1146 gfc_index_zero_node);
1148 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], to[n]);
1150 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1151 gfc_array_index_type,
1152 to[n], gfc_index_one_node);
1154 /* Check whether the size for this dimension is negative. */
1155 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1156 tmp, gfc_index_zero_node);
1157 cond = gfc_evaluate_now (cond, pre);
1159 if (n == 0)
1160 or_expr = cond;
1161 else
1162 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1163 boolean_type_node, or_expr, cond);
1165 size = fold_build2_loc (input_location, MULT_EXPR,
1166 gfc_array_index_type, size, tmp);
1167 size = gfc_evaluate_now (size, pre);
1171 /* Get the size of the array. */
1172 if (size && !callee_alloc)
1174 tree elemsize;
1175 /* If or_expr is true, then the extent in at least one
1176 dimension is zero and the size is set to zero. */
1177 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
1178 or_expr, gfc_index_zero_node, size);
1180 nelem = size;
1181 if (class_expr == NULL_TREE)
1182 elemsize = fold_convert (gfc_array_index_type,
1183 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1184 else
1185 elemsize = gfc_vtable_size_get (class_expr);
1187 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1188 size, elemsize);
1190 else
1192 nelem = size;
1193 size = NULL_TREE;
1196 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
1197 dynamic, dealloc);
1199 while (ss->parent)
1200 ss = ss->parent;
1202 if (ss->dimen > ss->loop->temp_dim)
1203 ss->loop->temp_dim = ss->dimen;
1205 return size;
1209 /* Return the number of iterations in a loop that starts at START,
1210 ends at END, and has step STEP. */
1212 static tree
1213 gfc_get_iteration_count (tree start, tree end, tree step)
1215 tree tmp;
1216 tree type;
1218 type = TREE_TYPE (step);
1219 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
1220 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
1221 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
1222 build_int_cst (type, 1));
1223 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
1224 build_int_cst (type, 0));
1225 return fold_convert (gfc_array_index_type, tmp);
1229 /* Extend the data in array DESC by EXTRA elements. */
1231 static void
1232 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
1234 tree arg0, arg1;
1235 tree tmp;
1236 tree size;
1237 tree ubound;
1239 if (integer_zerop (extra))
1240 return;
1242 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
1244 /* Add EXTRA to the upper bound. */
1245 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1246 ubound, extra);
1247 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
1249 /* Get the value of the current data pointer. */
1250 arg0 = gfc_conv_descriptor_data_get (desc);
1252 /* Calculate the new array size. */
1253 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
1254 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1255 ubound, gfc_index_one_node);
1256 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1257 fold_convert (size_type_node, tmp),
1258 fold_convert (size_type_node, size));
1260 /* Call the realloc() function. */
1261 tmp = gfc_call_realloc (pblock, arg0, arg1);
1262 gfc_conv_descriptor_data_set (pblock, desc, tmp);
1266 /* Return true if the bounds of iterator I can only be determined
1267 at run time. */
1269 static inline bool
1270 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
1272 return (i->start->expr_type != EXPR_CONSTANT
1273 || i->end->expr_type != EXPR_CONSTANT
1274 || i->step->expr_type != EXPR_CONSTANT);
1278 /* Split the size of constructor element EXPR into the sum of two terms,
1279 one of which can be determined at compile time and one of which must
1280 be calculated at run time. Set *SIZE to the former and return true
1281 if the latter might be nonzero. */
1283 static bool
1284 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
1286 if (expr->expr_type == EXPR_ARRAY)
1287 return gfc_get_array_constructor_size (size, expr->value.constructor);
1288 else if (expr->rank > 0)
1290 /* Calculate everything at run time. */
1291 mpz_set_ui (*size, 0);
1292 return true;
1294 else
1296 /* A single element. */
1297 mpz_set_ui (*size, 1);
1298 return false;
1303 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1304 of array constructor C. */
1306 static bool
1307 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1309 gfc_constructor *c;
1310 gfc_iterator *i;
1311 mpz_t val;
1312 mpz_t len;
1313 bool dynamic;
1315 mpz_set_ui (*size, 0);
1316 mpz_init (len);
1317 mpz_init (val);
1319 dynamic = false;
1320 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1322 i = c->iterator;
1323 if (i && gfc_iterator_has_dynamic_bounds (i))
1324 dynamic = true;
1325 else
1327 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1328 if (i)
1330 /* Multiply the static part of the element size by the
1331 number of iterations. */
1332 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1333 mpz_fdiv_q (val, val, i->step->value.integer);
1334 mpz_add_ui (val, val, 1);
1335 if (mpz_sgn (val) > 0)
1336 mpz_mul (len, len, val);
1337 else
1338 mpz_set_ui (len, 0);
1340 mpz_add (*size, *size, len);
1343 mpz_clear (len);
1344 mpz_clear (val);
1345 return dynamic;
1349 /* Make sure offset is a variable. */
1351 static void
1352 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1353 tree * offsetvar)
1355 /* We should have already created the offset variable. We cannot
1356 create it here because we may be in an inner scope. */
1357 gcc_assert (*offsetvar != NULL_TREE);
1358 gfc_add_modify (pblock, *offsetvar, *poffset);
1359 *poffset = *offsetvar;
1360 TREE_USED (*offsetvar) = 1;
1364 /* Variables needed for bounds-checking. */
1365 static bool first_len;
1366 static tree first_len_val;
1367 static bool typespec_chararray_ctor;
1369 static void
1370 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1371 tree offset, gfc_se * se, gfc_expr * expr)
1373 tree tmp;
1375 gfc_conv_expr (se, expr);
1377 /* Store the value. */
1378 tmp = build_fold_indirect_ref_loc (input_location,
1379 gfc_conv_descriptor_data_get (desc));
1380 tmp = gfc_build_array_ref (tmp, offset, NULL);
1382 if (expr->ts.type == BT_CHARACTER)
1384 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1385 tree esize;
1387 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1388 esize = fold_convert (gfc_charlen_type_node, esize);
1389 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1390 gfc_charlen_type_node, esize,
1391 build_int_cst (gfc_charlen_type_node,
1392 gfc_character_kinds[i].bit_size / 8));
1394 gfc_conv_string_parameter (se);
1395 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1397 /* The temporary is an array of pointers. */
1398 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1399 gfc_add_modify (&se->pre, tmp, se->expr);
1401 else
1403 /* The temporary is an array of string values. */
1404 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1405 /* We know the temporary and the value will be the same length,
1406 so can use memcpy. */
1407 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1408 se->string_length, se->expr, expr->ts.kind);
1410 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1412 if (first_len)
1414 gfc_add_modify (&se->pre, first_len_val,
1415 se->string_length);
1416 first_len = false;
1418 else
1420 /* Verify that all constructor elements are of the same
1421 length. */
1422 tree cond = fold_build2_loc (input_location, NE_EXPR,
1423 boolean_type_node, first_len_val,
1424 se->string_length);
1425 gfc_trans_runtime_check
1426 (true, false, cond, &se->pre, &expr->where,
1427 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1428 fold_convert (long_integer_type_node, first_len_val),
1429 fold_convert (long_integer_type_node, se->string_length));
1433 else
1435 /* TODO: Should the frontend already have done this conversion? */
1436 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1437 gfc_add_modify (&se->pre, tmp, se->expr);
1440 gfc_add_block_to_block (pblock, &se->pre);
1441 gfc_add_block_to_block (pblock, &se->post);
1445 /* Add the contents of an array to the constructor. DYNAMIC is as for
1446 gfc_trans_array_constructor_value. */
1448 static void
1449 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1450 tree type ATTRIBUTE_UNUSED,
1451 tree desc, gfc_expr * expr,
1452 tree * poffset, tree * offsetvar,
1453 bool dynamic)
1455 gfc_se se;
1456 gfc_ss *ss;
1457 gfc_loopinfo loop;
1458 stmtblock_t body;
1459 tree tmp;
1460 tree size;
1461 int n;
1463 /* We need this to be a variable so we can increment it. */
1464 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1466 gfc_init_se (&se, NULL);
1468 /* Walk the array expression. */
1469 ss = gfc_walk_expr (expr);
1470 gcc_assert (ss != gfc_ss_terminator);
1472 /* Initialize the scalarizer. */
1473 gfc_init_loopinfo (&loop);
1474 gfc_add_ss_to_loop (&loop, ss);
1476 /* Initialize the loop. */
1477 gfc_conv_ss_startstride (&loop);
1478 gfc_conv_loop_setup (&loop, &expr->where);
1480 /* Make sure the constructed array has room for the new data. */
1481 if (dynamic)
1483 /* Set SIZE to the total number of elements in the subarray. */
1484 size = gfc_index_one_node;
1485 for (n = 0; n < loop.dimen; n++)
1487 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1488 gfc_index_one_node);
1489 size = fold_build2_loc (input_location, MULT_EXPR,
1490 gfc_array_index_type, size, tmp);
1493 /* Grow the constructed array by SIZE elements. */
1494 gfc_grow_array (&loop.pre, desc, size);
1497 /* Make the loop body. */
1498 gfc_mark_ss_chain_used (ss, 1);
1499 gfc_start_scalarized_body (&loop, &body);
1500 gfc_copy_loopinfo_to_se (&se, &loop);
1501 se.ss = ss;
1503 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1504 gcc_assert (se.ss == gfc_ss_terminator);
1506 /* Increment the offset. */
1507 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1508 *poffset, gfc_index_one_node);
1509 gfc_add_modify (&body, *poffset, tmp);
1511 /* Finish the loop. */
1512 gfc_trans_scalarizing_loops (&loop, &body);
1513 gfc_add_block_to_block (&loop.pre, &loop.post);
1514 tmp = gfc_finish_block (&loop.pre);
1515 gfc_add_expr_to_block (pblock, tmp);
1517 gfc_cleanup_loop (&loop);
1521 /* Assign the values to the elements of an array constructor. DYNAMIC
1522 is true if descriptor DESC only contains enough data for the static
1523 size calculated by gfc_get_array_constructor_size. When true, memory
1524 for the dynamic parts must be allocated using realloc. */
1526 static void
1527 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1528 tree desc, gfc_constructor_base base,
1529 tree * poffset, tree * offsetvar,
1530 bool dynamic)
1532 tree tmp;
1533 tree start = NULL_TREE;
1534 tree end = NULL_TREE;
1535 tree step = NULL_TREE;
1536 stmtblock_t body;
1537 gfc_se se;
1538 mpz_t size;
1539 gfc_constructor *c;
1541 tree shadow_loopvar = NULL_TREE;
1542 gfc_saved_var saved_loopvar;
1544 mpz_init (size);
1545 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1547 /* If this is an iterator or an array, the offset must be a variable. */
1548 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1549 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1551 /* Shadowing the iterator avoids changing its value and saves us from
1552 keeping track of it. Further, it makes sure that there's always a
1553 backend-decl for the symbol, even if there wasn't one before,
1554 e.g. in the case of an iterator that appears in a specification
1555 expression in an interface mapping. */
1556 if (c->iterator)
1558 gfc_symbol *sym;
1559 tree type;
1561 /* Evaluate loop bounds before substituting the loop variable
1562 in case they depend on it. Such a case is invalid, but it is
1563 not more expensive to do the right thing here.
1564 See PR 44354. */
1565 gfc_init_se (&se, NULL);
1566 gfc_conv_expr_val (&se, c->iterator->start);
1567 gfc_add_block_to_block (pblock, &se.pre);
1568 start = gfc_evaluate_now (se.expr, pblock);
1570 gfc_init_se (&se, NULL);
1571 gfc_conv_expr_val (&se, c->iterator->end);
1572 gfc_add_block_to_block (pblock, &se.pre);
1573 end = gfc_evaluate_now (se.expr, pblock);
1575 gfc_init_se (&se, NULL);
1576 gfc_conv_expr_val (&se, c->iterator->step);
1577 gfc_add_block_to_block (pblock, &se.pre);
1578 step = gfc_evaluate_now (se.expr, pblock);
1580 sym = c->iterator->var->symtree->n.sym;
1581 type = gfc_typenode_for_spec (&sym->ts);
1583 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1584 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1587 gfc_start_block (&body);
1589 if (c->expr->expr_type == EXPR_ARRAY)
1591 /* Array constructors can be nested. */
1592 gfc_trans_array_constructor_value (&body, type, desc,
1593 c->expr->value.constructor,
1594 poffset, offsetvar, dynamic);
1596 else if (c->expr->rank > 0)
1598 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1599 poffset, offsetvar, dynamic);
1601 else
1603 /* This code really upsets the gimplifier so don't bother for now. */
1604 gfc_constructor *p;
1605 HOST_WIDE_INT n;
1606 HOST_WIDE_INT size;
1608 p = c;
1609 n = 0;
1610 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1612 p = gfc_constructor_next (p);
1613 n++;
1615 if (n < 4)
1617 /* Scalar values. */
1618 gfc_init_se (&se, NULL);
1619 gfc_trans_array_ctor_element (&body, desc, *poffset,
1620 &se, c->expr);
1622 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1623 gfc_array_index_type,
1624 *poffset, gfc_index_one_node);
1626 else
1628 /* Collect multiple scalar constants into a constructor. */
1629 vec<constructor_elt, va_gc> *v = NULL;
1630 tree init;
1631 tree bound;
1632 tree tmptype;
1633 HOST_WIDE_INT idx = 0;
1635 p = c;
1636 /* Count the number of consecutive scalar constants. */
1637 while (p && !(p->iterator
1638 || p->expr->expr_type != EXPR_CONSTANT))
1640 gfc_init_se (&se, NULL);
1641 gfc_conv_constant (&se, p->expr);
1643 if (c->expr->ts.type != BT_CHARACTER)
1644 se.expr = fold_convert (type, se.expr);
1645 /* For constant character array constructors we build
1646 an array of pointers. */
1647 else if (POINTER_TYPE_P (type))
1648 se.expr = gfc_build_addr_expr
1649 (gfc_get_pchar_type (p->expr->ts.kind),
1650 se.expr);
1652 CONSTRUCTOR_APPEND_ELT (v,
1653 build_int_cst (gfc_array_index_type,
1654 idx++),
1655 se.expr);
1656 c = p;
1657 p = gfc_constructor_next (p);
1660 bound = size_int (n - 1);
1661 /* Create an array type to hold them. */
1662 tmptype = build_range_type (gfc_array_index_type,
1663 gfc_index_zero_node, bound);
1664 tmptype = build_array_type (type, tmptype);
1666 init = build_constructor (tmptype, v);
1667 TREE_CONSTANT (init) = 1;
1668 TREE_STATIC (init) = 1;
1669 /* Create a static variable to hold the data. */
1670 tmp = gfc_create_var (tmptype, "data");
1671 TREE_STATIC (tmp) = 1;
1672 TREE_CONSTANT (tmp) = 1;
1673 TREE_READONLY (tmp) = 1;
1674 DECL_INITIAL (tmp) = init;
1675 init = tmp;
1677 /* Use BUILTIN_MEMCPY to assign the values. */
1678 tmp = gfc_conv_descriptor_data_get (desc);
1679 tmp = build_fold_indirect_ref_loc (input_location,
1680 tmp);
1681 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1682 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1683 init = gfc_build_addr_expr (NULL_TREE, init);
1685 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1686 bound = build_int_cst (size_type_node, n * size);
1687 tmp = build_call_expr_loc (input_location,
1688 builtin_decl_explicit (BUILT_IN_MEMCPY),
1689 3, tmp, init, bound);
1690 gfc_add_expr_to_block (&body, tmp);
1692 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1693 gfc_array_index_type, *poffset,
1694 build_int_cst (gfc_array_index_type, n));
1696 if (!INTEGER_CST_P (*poffset))
1698 gfc_add_modify (&body, *offsetvar, *poffset);
1699 *poffset = *offsetvar;
1703 /* The frontend should already have done any expansions
1704 at compile-time. */
1705 if (!c->iterator)
1707 /* Pass the code as is. */
1708 tmp = gfc_finish_block (&body);
1709 gfc_add_expr_to_block (pblock, tmp);
1711 else
1713 /* Build the implied do-loop. */
1714 stmtblock_t implied_do_block;
1715 tree cond;
1716 tree exit_label;
1717 tree loopbody;
1718 tree tmp2;
1720 loopbody = gfc_finish_block (&body);
1722 /* Create a new block that holds the implied-do loop. A temporary
1723 loop-variable is used. */
1724 gfc_start_block(&implied_do_block);
1726 /* Initialize the loop. */
1727 gfc_add_modify (&implied_do_block, shadow_loopvar, start);
1729 /* If this array expands dynamically, and the number of iterations
1730 is not constant, we won't have allocated space for the static
1731 part of C->EXPR's size. Do that now. */
1732 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1734 /* Get the number of iterations. */
1735 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1737 /* Get the static part of C->EXPR's size. */
1738 gfc_get_array_constructor_element_size (&size, c->expr);
1739 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1741 /* Grow the array by TMP * TMP2 elements. */
1742 tmp = fold_build2_loc (input_location, MULT_EXPR,
1743 gfc_array_index_type, tmp, tmp2);
1744 gfc_grow_array (&implied_do_block, desc, tmp);
1747 /* Generate the loop body. */
1748 exit_label = gfc_build_label_decl (NULL_TREE);
1749 gfc_start_block (&body);
1751 /* Generate the exit condition. Depending on the sign of
1752 the step variable we have to generate the correct
1753 comparison. */
1754 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1755 step, build_int_cst (TREE_TYPE (step), 0));
1756 cond = fold_build3_loc (input_location, COND_EXPR,
1757 boolean_type_node, tmp,
1758 fold_build2_loc (input_location, GT_EXPR,
1759 boolean_type_node, shadow_loopvar, end),
1760 fold_build2_loc (input_location, LT_EXPR,
1761 boolean_type_node, shadow_loopvar, end));
1762 tmp = build1_v (GOTO_EXPR, exit_label);
1763 TREE_USED (exit_label) = 1;
1764 tmp = build3_v (COND_EXPR, cond, tmp,
1765 build_empty_stmt (input_location));
1766 gfc_add_expr_to_block (&body, tmp);
1768 /* The main loop body. */
1769 gfc_add_expr_to_block (&body, loopbody);
1771 /* Increase loop variable by step. */
1772 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1773 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1774 step);
1775 gfc_add_modify (&body, shadow_loopvar, tmp);
1777 /* Finish the loop. */
1778 tmp = gfc_finish_block (&body);
1779 tmp = build1_v (LOOP_EXPR, tmp);
1780 gfc_add_expr_to_block (&implied_do_block, tmp);
1782 /* Add the exit label. */
1783 tmp = build1_v (LABEL_EXPR, exit_label);
1784 gfc_add_expr_to_block (&implied_do_block, tmp);
1786 /* Finish the implied-do loop. */
1787 tmp = gfc_finish_block(&implied_do_block);
1788 gfc_add_expr_to_block(pblock, tmp);
1790 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1793 mpz_clear (size);
1797 /* A catch-all to obtain the string length for anything that is not
1798 a substring of non-constant length, a constant, array or variable. */
1800 static void
1801 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1803 gfc_se se;
1805 /* Don't bother if we already know the length is a constant. */
1806 if (*len && INTEGER_CST_P (*len))
1807 return;
1809 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1810 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1812 /* This is easy. */
1813 gfc_conv_const_charlen (e->ts.u.cl);
1814 *len = e->ts.u.cl->backend_decl;
1816 else
1818 /* Otherwise, be brutal even if inefficient. */
1819 gfc_init_se (&se, NULL);
1821 /* No function call, in case of side effects. */
1822 se.no_function_call = 1;
1823 if (e->rank == 0)
1824 gfc_conv_expr (&se, e);
1825 else
1826 gfc_conv_expr_descriptor (&se, e);
1828 /* Fix the value. */
1829 *len = gfc_evaluate_now (se.string_length, &se.pre);
1831 gfc_add_block_to_block (block, &se.pre);
1832 gfc_add_block_to_block (block, &se.post);
1834 e->ts.u.cl->backend_decl = *len;
1839 /* Figure out the string length of a variable reference expression.
1840 Used by get_array_ctor_strlen. */
1842 static void
1843 get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
1845 gfc_ref *ref;
1846 gfc_typespec *ts;
1847 mpz_t char_len;
1849 /* Don't bother if we already know the length is a constant. */
1850 if (*len && INTEGER_CST_P (*len))
1851 return;
1853 ts = &expr->symtree->n.sym->ts;
1854 for (ref = expr->ref; ref; ref = ref->next)
1856 switch (ref->type)
1858 case REF_ARRAY:
1859 /* Array references don't change the string length. */
1860 break;
1862 case REF_COMPONENT:
1863 /* Use the length of the component. */
1864 ts = &ref->u.c.component->ts;
1865 break;
1867 case REF_SUBSTRING:
1868 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1869 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1871 /* Note that this might evaluate expr. */
1872 get_array_ctor_all_strlen (block, expr, len);
1873 return;
1875 mpz_init_set_ui (char_len, 1);
1876 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1877 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1878 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1879 *len = convert (gfc_charlen_type_node, *len);
1880 mpz_clear (char_len);
1881 return;
1883 default:
1884 gcc_unreachable ();
1888 *len = ts->u.cl->backend_decl;
1892 /* Figure out the string length of a character array constructor.
1893 If len is NULL, don't calculate the length; this happens for recursive calls
1894 when a sub-array-constructor is an element but not at the first position,
1895 so when we're not interested in the length.
1896 Returns TRUE if all elements are character constants. */
1898 bool
1899 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
1901 gfc_constructor *c;
1902 bool is_const;
1904 is_const = TRUE;
1906 if (gfc_constructor_first (base) == NULL)
1908 if (len)
1909 *len = build_int_cstu (gfc_charlen_type_node, 0);
1910 return is_const;
1913 /* Loop over all constructor elements to find out is_const, but in len we
1914 want to store the length of the first, not the last, element. We can
1915 of course exit the loop as soon as is_const is found to be false. */
1916 for (c = gfc_constructor_first (base);
1917 c && is_const; c = gfc_constructor_next (c))
1919 switch (c->expr->expr_type)
1921 case EXPR_CONSTANT:
1922 if (len && !(*len && INTEGER_CST_P (*len)))
1923 *len = build_int_cstu (gfc_charlen_type_node,
1924 c->expr->value.character.length);
1925 break;
1927 case EXPR_ARRAY:
1928 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1929 is_const = false;
1930 break;
1932 case EXPR_VARIABLE:
1933 is_const = false;
1934 if (len)
1935 get_array_ctor_var_strlen (block, c->expr, len);
1936 break;
1938 default:
1939 is_const = false;
1940 if (len)
1941 get_array_ctor_all_strlen (block, c->expr, len);
1942 break;
1945 /* After the first iteration, we don't want the length modified. */
1946 len = NULL;
1949 return is_const;
1952 /* Check whether the array constructor C consists entirely of constant
1953 elements, and if so returns the number of those elements, otherwise
1954 return zero. Note, an empty or NULL array constructor returns zero. */
1956 unsigned HOST_WIDE_INT
1957 gfc_constant_array_constructor_p (gfc_constructor_base base)
1959 unsigned HOST_WIDE_INT nelem = 0;
1961 gfc_constructor *c = gfc_constructor_first (base);
1962 while (c)
1964 if (c->iterator
1965 || c->expr->rank > 0
1966 || c->expr->expr_type != EXPR_CONSTANT)
1967 return 0;
1968 c = gfc_constructor_next (c);
1969 nelem++;
1971 return nelem;
1975 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1976 and the tree type of it's elements, TYPE, return a static constant
1977 variable that is compile-time initialized. */
1979 tree
1980 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1982 tree tmptype, init, tmp;
1983 HOST_WIDE_INT nelem;
1984 gfc_constructor *c;
1985 gfc_array_spec as;
1986 gfc_se se;
1987 int i;
1988 vec<constructor_elt, va_gc> *v = NULL;
1990 /* First traverse the constructor list, converting the constants
1991 to tree to build an initializer. */
1992 nelem = 0;
1993 c = gfc_constructor_first (expr->value.constructor);
1994 while (c)
1996 gfc_init_se (&se, NULL);
1997 gfc_conv_constant (&se, c->expr);
1998 if (c->expr->ts.type != BT_CHARACTER)
1999 se.expr = fold_convert (type, se.expr);
2000 else if (POINTER_TYPE_P (type))
2001 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
2002 se.expr);
2003 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
2004 se.expr);
2005 c = gfc_constructor_next (c);
2006 nelem++;
2009 /* Next determine the tree type for the array. We use the gfortran
2010 front-end's gfc_get_nodesc_array_type in order to create a suitable
2011 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
2013 memset (&as, 0, sizeof (gfc_array_spec));
2015 as.rank = expr->rank;
2016 as.type = AS_EXPLICIT;
2017 if (!expr->shape)
2019 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2020 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
2021 NULL, nelem - 1);
2023 else
2024 for (i = 0; i < expr->rank; i++)
2026 int tmp = (int) mpz_get_si (expr->shape[i]);
2027 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
2028 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
2029 NULL, tmp - 1);
2032 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
2034 /* as is not needed anymore. */
2035 for (i = 0; i < as.rank + as.corank; i++)
2037 gfc_free_expr (as.lower[i]);
2038 gfc_free_expr (as.upper[i]);
2041 init = build_constructor (tmptype, v);
2043 TREE_CONSTANT (init) = 1;
2044 TREE_STATIC (init) = 1;
2046 tmp = gfc_create_var (tmptype, "A");
2047 TREE_STATIC (tmp) = 1;
2048 TREE_CONSTANT (tmp) = 1;
2049 TREE_READONLY (tmp) = 1;
2050 DECL_INITIAL (tmp) = init;
2052 return tmp;
2056 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
2057 This mostly initializes the scalarizer state info structure with the
2058 appropriate values to directly use the array created by the function
2059 gfc_build_constant_array_constructor. */
2061 static void
2062 trans_constant_array_constructor (gfc_ss * ss, tree type)
2064 gfc_array_info *info;
2065 tree tmp;
2066 int i;
2068 tmp = gfc_build_constant_array_constructor (ss->info->expr, type);
2070 info = &ss->info->data.array;
2072 info->descriptor = tmp;
2073 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
2074 info->offset = gfc_index_zero_node;
2076 for (i = 0; i < ss->dimen; i++)
2078 info->delta[i] = gfc_index_zero_node;
2079 info->start[i] = gfc_index_zero_node;
2080 info->end[i] = gfc_index_zero_node;
2081 info->stride[i] = gfc_index_one_node;
2086 static int
2087 get_rank (gfc_loopinfo *loop)
2089 int rank;
2091 rank = 0;
2092 for (; loop; loop = loop->parent)
2093 rank += loop->dimen;
2095 return rank;
2099 /* Helper routine of gfc_trans_array_constructor to determine if the
2100 bounds of the loop specified by LOOP are constant and simple enough
2101 to use with trans_constant_array_constructor. Returns the
2102 iteration count of the loop if suitable, and NULL_TREE otherwise. */
2104 static tree
2105 constant_array_constructor_loop_size (gfc_loopinfo * l)
2107 gfc_loopinfo *loop;
2108 tree size = gfc_index_one_node;
2109 tree tmp;
2110 int i, total_dim;
2112 total_dim = get_rank (l);
2114 for (loop = l; loop; loop = loop->parent)
2116 for (i = 0; i < loop->dimen; i++)
2118 /* If the bounds aren't constant, return NULL_TREE. */
2119 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
2120 return NULL_TREE;
2121 if (!integer_zerop (loop->from[i]))
2123 /* Only allow nonzero "from" in one-dimensional arrays. */
2124 if (total_dim != 1)
2125 return NULL_TREE;
2126 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2127 gfc_array_index_type,
2128 loop->to[i], loop->from[i]);
2130 else
2131 tmp = loop->to[i];
2132 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2133 gfc_array_index_type, tmp, gfc_index_one_node);
2134 size = fold_build2_loc (input_location, MULT_EXPR,
2135 gfc_array_index_type, size, tmp);
2139 return size;
2143 static tree *
2144 get_loop_upper_bound_for_array (gfc_ss *array, int array_dim)
2146 gfc_ss *ss;
2147 int n;
2149 gcc_assert (array->nested_ss == NULL);
2151 for (ss = array; ss; ss = ss->parent)
2152 for (n = 0; n < ss->loop->dimen; n++)
2153 if (array_dim == get_array_ref_dim_for_loop_dim (ss, n))
2154 return &(ss->loop->to[n]);
2156 gcc_unreachable ();
2160 static gfc_loopinfo *
2161 outermost_loop (gfc_loopinfo * loop)
2163 while (loop->parent != NULL)
2164 loop = loop->parent;
2166 return loop;
2170 /* Array constructors are handled by constructing a temporary, then using that
2171 within the scalarization loop. This is not optimal, but seems by far the
2172 simplest method. */
2174 static void
2175 trans_array_constructor (gfc_ss * ss, locus * where)
2177 gfc_constructor_base c;
2178 tree offset;
2179 tree offsetvar;
2180 tree desc;
2181 tree type;
2182 tree tmp;
2183 tree *loop_ubound0;
2184 bool dynamic;
2185 bool old_first_len, old_typespec_chararray_ctor;
2186 tree old_first_len_val;
2187 gfc_loopinfo *loop, *outer_loop;
2188 gfc_ss_info *ss_info;
2189 gfc_expr *expr;
2190 gfc_ss *s;
2192 /* Save the old values for nested checking. */
2193 old_first_len = first_len;
2194 old_first_len_val = first_len_val;
2195 old_typespec_chararray_ctor = typespec_chararray_ctor;
2197 loop = ss->loop;
2198 outer_loop = outermost_loop (loop);
2199 ss_info = ss->info;
2200 expr = ss_info->expr;
2202 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
2203 typespec was given for the array constructor. */
2204 typespec_chararray_ctor = (expr->ts.u.cl
2205 && expr->ts.u.cl->length_from_typespec);
2207 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2208 && expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
2210 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
2211 first_len = true;
2214 gcc_assert (ss->dimen == ss->loop->dimen);
2216 c = expr->value.constructor;
2217 if (expr->ts.type == BT_CHARACTER)
2219 bool const_string;
2221 /* get_array_ctor_strlen walks the elements of the constructor, if a
2222 typespec was given, we already know the string length and want the one
2223 specified there. */
2224 if (typespec_chararray_ctor && expr->ts.u.cl->length
2225 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
2227 gfc_se length_se;
2229 const_string = false;
2230 gfc_init_se (&length_se, NULL);
2231 gfc_conv_expr_type (&length_se, expr->ts.u.cl->length,
2232 gfc_charlen_type_node);
2233 ss_info->string_length = length_se.expr;
2234 gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
2235 gfc_add_block_to_block (&outer_loop->post, &length_se.post);
2237 else
2238 const_string = get_array_ctor_strlen (&outer_loop->pre, c,
2239 &ss_info->string_length);
2241 /* Complex character array constructors should have been taken care of
2242 and not end up here. */
2243 gcc_assert (ss_info->string_length);
2245 expr->ts.u.cl->backend_decl = ss_info->string_length;
2247 type = gfc_get_character_type_len (expr->ts.kind, ss_info->string_length);
2248 if (const_string)
2249 type = build_pointer_type (type);
2251 else
2252 type = gfc_typenode_for_spec (&expr->ts);
2254 /* See if the constructor determines the loop bounds. */
2255 dynamic = false;
2257 loop_ubound0 = get_loop_upper_bound_for_array (ss, 0);
2259 if (expr->shape && get_rank (loop) > 1 && *loop_ubound0 == NULL_TREE)
2261 /* We have a multidimensional parameter. */
2262 for (s = ss; s; s = s->parent)
2264 int n;
2265 for (n = 0; n < s->loop->dimen; n++)
2267 s->loop->from[n] = gfc_index_zero_node;
2268 s->loop->to[n] = gfc_conv_mpz_to_tree (expr->shape[s->dim[n]],
2269 gfc_index_integer_kind);
2270 s->loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
2271 gfc_array_index_type,
2272 s->loop->to[n],
2273 gfc_index_one_node);
2278 if (*loop_ubound0 == NULL_TREE)
2280 mpz_t size;
2282 /* We should have a 1-dimensional, zero-based loop. */
2283 gcc_assert (loop->parent == NULL && loop->nested == NULL);
2284 gcc_assert (loop->dimen == 1);
2285 gcc_assert (integer_zerop (loop->from[0]));
2287 /* Split the constructor size into a static part and a dynamic part.
2288 Allocate the static size up-front and record whether the dynamic
2289 size might be nonzero. */
2290 mpz_init (size);
2291 dynamic = gfc_get_array_constructor_size (&size, c);
2292 mpz_sub_ui (size, size, 1);
2293 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
2294 mpz_clear (size);
2297 /* Special case constant array constructors. */
2298 if (!dynamic)
2300 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
2301 if (nelem > 0)
2303 tree size = constant_array_constructor_loop_size (loop);
2304 if (size && compare_tree_int (size, nelem) == 0)
2306 trans_constant_array_constructor (ss, type);
2307 goto finish;
2312 if (TREE_CODE (*loop_ubound0) == VAR_DECL)
2313 dynamic = true;
2315 gfc_trans_create_temp_array (&outer_loop->pre, &outer_loop->post, ss, type,
2316 NULL_TREE, dynamic, true, false, where);
2318 desc = ss_info->data.array.descriptor;
2319 offset = gfc_index_zero_node;
2320 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
2321 TREE_NO_WARNING (offsetvar) = 1;
2322 TREE_USED (offsetvar) = 0;
2323 gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
2324 &offset, &offsetvar, dynamic);
2326 /* If the array grows dynamically, the upper bound of the loop variable
2327 is determined by the array's final upper bound. */
2328 if (dynamic)
2330 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2331 gfc_array_index_type,
2332 offsetvar, gfc_index_one_node);
2333 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2334 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
2335 if (*loop_ubound0 && TREE_CODE (*loop_ubound0) == VAR_DECL)
2336 gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
2337 else
2338 *loop_ubound0 = tmp;
2341 if (TREE_USED (offsetvar))
2342 pushdecl (offsetvar);
2343 else
2344 gcc_assert (INTEGER_CST_P (offset));
2346 #if 0
2347 /* Disable bound checking for now because it's probably broken. */
2348 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2350 gcc_unreachable ();
2352 #endif
2354 finish:
2355 /* Restore old values of globals. */
2356 first_len = old_first_len;
2357 first_len_val = old_first_len_val;
2358 typespec_chararray_ctor = old_typespec_chararray_ctor;
2362 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2363 called after evaluating all of INFO's vector dimensions. Go through
2364 each such vector dimension and see if we can now fill in any missing
2365 loop bounds. */
2367 static void
2368 set_vector_loop_bounds (gfc_ss * ss)
2370 gfc_loopinfo *loop, *outer_loop;
2371 gfc_array_info *info;
2372 gfc_se se;
2373 tree tmp;
2374 tree desc;
2375 tree zero;
2376 int n;
2377 int dim;
2379 outer_loop = outermost_loop (ss->loop);
2381 info = &ss->info->data.array;
2383 for (; ss; ss = ss->parent)
2385 loop = ss->loop;
2387 for (n = 0; n < loop->dimen; n++)
2389 dim = ss->dim[n];
2390 if (info->ref->u.ar.dimen_type[dim] != DIMEN_VECTOR
2391 || loop->to[n] != NULL)
2392 continue;
2394 /* Loop variable N indexes vector dimension DIM, and we don't
2395 yet know the upper bound of loop variable N. Set it to the
2396 difference between the vector's upper and lower bounds. */
2397 gcc_assert (loop->from[n] == gfc_index_zero_node);
2398 gcc_assert (info->subscript[dim]
2399 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2401 gfc_init_se (&se, NULL);
2402 desc = info->subscript[dim]->info->data.array.descriptor;
2403 zero = gfc_rank_cst[0];
2404 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2405 gfc_array_index_type,
2406 gfc_conv_descriptor_ubound_get (desc, zero),
2407 gfc_conv_descriptor_lbound_get (desc, zero));
2408 tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
2409 loop->to[n] = tmp;
2415 /* Add the pre and post chains for all the scalar expressions in a SS chain
2416 to loop. This is called after the loop parameters have been calculated,
2417 but before the actual scalarizing loops. */
2419 static void
2420 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2421 locus * where)
2423 gfc_loopinfo *nested_loop, *outer_loop;
2424 gfc_se se;
2425 gfc_ss_info *ss_info;
2426 gfc_array_info *info;
2427 gfc_expr *expr;
2428 int n;
2430 /* Don't evaluate the arguments for realloc_lhs_loop_for_fcn_call; otherwise,
2431 arguments could get evaluated multiple times. */
2432 if (ss->is_alloc_lhs)
2433 return;
2435 outer_loop = outermost_loop (loop);
2437 /* TODO: This can generate bad code if there are ordering dependencies,
2438 e.g., a callee allocated function and an unknown size constructor. */
2439 gcc_assert (ss != NULL);
2441 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2443 gcc_assert (ss);
2445 /* Cross loop arrays are handled from within the most nested loop. */
2446 if (ss->nested_ss != NULL)
2447 continue;
2449 ss_info = ss->info;
2450 expr = ss_info->expr;
2451 info = &ss_info->data.array;
2453 switch (ss_info->type)
2455 case GFC_SS_SCALAR:
2456 /* Scalar expression. Evaluate this now. This includes elemental
2457 dimension indices, but not array section bounds. */
2458 gfc_init_se (&se, NULL);
2459 gfc_conv_expr (&se, expr);
2460 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2462 if (expr->ts.type != BT_CHARACTER)
2464 /* Move the evaluation of scalar expressions outside the
2465 scalarization loop, except for WHERE assignments. */
2466 if (subscript)
2467 se.expr = convert(gfc_array_index_type, se.expr);
2468 if (!ss_info->where)
2469 se.expr = gfc_evaluate_now (se.expr, &outer_loop->pre);
2470 gfc_add_block_to_block (&outer_loop->pre, &se.post);
2472 else
2473 gfc_add_block_to_block (&outer_loop->post, &se.post);
2475 ss_info->data.scalar.value = se.expr;
2476 ss_info->string_length = se.string_length;
2477 break;
2479 case GFC_SS_REFERENCE:
2480 /* Scalar argument to elemental procedure. */
2481 gfc_init_se (&se, NULL);
2482 if (ss_info->can_be_null_ref)
2484 /* If the actual argument can be absent (in other words, it can
2485 be a NULL reference), don't try to evaluate it; pass instead
2486 the reference directly. */
2487 gfc_conv_expr_reference (&se, expr);
2489 else
2491 /* Otherwise, evaluate the argument outside the loop and pass
2492 a reference to the value. */
2493 gfc_conv_expr (&se, expr);
2495 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2496 gfc_add_block_to_block (&outer_loop->post, &se.post);
2497 if (gfc_is_class_scalar_expr (expr))
2498 /* This is necessary because the dynamic type will always be
2499 large than the declared type. In consequence, assigning
2500 the value to a temporary could segfault.
2501 OOP-TODO: see if this is generally correct or is the value
2502 has to be written to an allocated temporary, whose address
2503 is passed via ss_info. */
2504 ss_info->data.scalar.value = se.expr;
2505 else
2506 ss_info->data.scalar.value = gfc_evaluate_now (se.expr,
2507 &outer_loop->pre);
2509 ss_info->string_length = se.string_length;
2510 break;
2512 case GFC_SS_SECTION:
2513 /* Add the expressions for scalar and vector subscripts. */
2514 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2515 if (info->subscript[n])
2516 gfc_add_loop_ss_code (loop, info->subscript[n], true, where);
2518 set_vector_loop_bounds (ss);
2519 break;
2521 case GFC_SS_VECTOR:
2522 /* Get the vector's descriptor and store it in SS. */
2523 gfc_init_se (&se, NULL);
2524 gfc_conv_expr_descriptor (&se, expr);
2525 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2526 gfc_add_block_to_block (&outer_loop->post, &se.post);
2527 info->descriptor = se.expr;
2528 break;
2530 case GFC_SS_INTRINSIC:
2531 gfc_add_intrinsic_ss_code (loop, ss);
2532 break;
2534 case GFC_SS_FUNCTION:
2535 /* Array function return value. We call the function and save its
2536 result in a temporary for use inside the loop. */
2537 gfc_init_se (&se, NULL);
2538 se.loop = loop;
2539 se.ss = ss;
2540 gfc_conv_expr (&se, expr);
2541 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2542 gfc_add_block_to_block (&outer_loop->post, &se.post);
2543 ss_info->string_length = se.string_length;
2544 break;
2546 case GFC_SS_CONSTRUCTOR:
2547 if (expr->ts.type == BT_CHARACTER
2548 && ss_info->string_length == NULL
2549 && expr->ts.u.cl
2550 && expr->ts.u.cl->length)
2552 gfc_init_se (&se, NULL);
2553 gfc_conv_expr_type (&se, expr->ts.u.cl->length,
2554 gfc_charlen_type_node);
2555 ss_info->string_length = se.expr;
2556 gfc_add_block_to_block (&outer_loop->pre, &se.pre);
2557 gfc_add_block_to_block (&outer_loop->post, &se.post);
2559 trans_array_constructor (ss, where);
2560 break;
2562 case GFC_SS_TEMP:
2563 case GFC_SS_COMPONENT:
2564 /* Do nothing. These are handled elsewhere. */
2565 break;
2567 default:
2568 gcc_unreachable ();
2572 if (!subscript)
2573 for (nested_loop = loop->nested; nested_loop;
2574 nested_loop = nested_loop->next)
2575 gfc_add_loop_ss_code (nested_loop, nested_loop->ss, subscript, where);
2579 /* Translate expressions for the descriptor and data pointer of a SS. */
2580 /*GCC ARRAYS*/
2582 static void
2583 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2585 gfc_se se;
2586 gfc_ss_info *ss_info;
2587 gfc_array_info *info;
2588 tree tmp;
2590 ss_info = ss->info;
2591 info = &ss_info->data.array;
2593 /* Get the descriptor for the array to be scalarized. */
2594 gcc_assert (ss_info->expr->expr_type == EXPR_VARIABLE);
2595 gfc_init_se (&se, NULL);
2596 se.descriptor_only = 1;
2597 gfc_conv_expr_lhs (&se, ss_info->expr);
2598 gfc_add_block_to_block (block, &se.pre);
2599 info->descriptor = se.expr;
2600 ss_info->string_length = se.string_length;
2602 if (base)
2604 /* Also the data pointer. */
2605 tmp = gfc_conv_array_data (se.expr);
2606 /* If this is a variable or address of a variable we use it directly.
2607 Otherwise we must evaluate it now to avoid breaking dependency
2608 analysis by pulling the expressions for elemental array indices
2609 inside the loop. */
2610 if (!(DECL_P (tmp)
2611 || (TREE_CODE (tmp) == ADDR_EXPR
2612 && DECL_P (TREE_OPERAND (tmp, 0)))))
2613 tmp = gfc_evaluate_now (tmp, block);
2614 info->data = tmp;
2616 tmp = gfc_conv_array_offset (se.expr);
2617 info->offset = gfc_evaluate_now (tmp, block);
2619 /* Make absolutely sure that the saved_offset is indeed saved
2620 so that the variable is still accessible after the loops
2621 are translated. */
2622 info->saved_offset = info->offset;
2627 /* Initialize a gfc_loopinfo structure. */
2629 void
2630 gfc_init_loopinfo (gfc_loopinfo * loop)
2632 int n;
2634 memset (loop, 0, sizeof (gfc_loopinfo));
2635 gfc_init_block (&loop->pre);
2636 gfc_init_block (&loop->post);
2638 /* Initially scalarize in order and default to no loop reversal. */
2639 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2641 loop->order[n] = n;
2642 loop->reverse[n] = GFC_INHIBIT_REVERSE;
2645 loop->ss = gfc_ss_terminator;
2649 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2650 chain. */
2652 void
2653 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2655 se->loop = loop;
2659 /* Return an expression for the data pointer of an array. */
2661 tree
2662 gfc_conv_array_data (tree descriptor)
2664 tree type;
2666 type = TREE_TYPE (descriptor);
2667 if (GFC_ARRAY_TYPE_P (type))
2669 if (TREE_CODE (type) == POINTER_TYPE)
2670 return descriptor;
2671 else
2673 /* Descriptorless arrays. */
2674 return gfc_build_addr_expr (NULL_TREE, descriptor);
2677 else
2678 return gfc_conv_descriptor_data_get (descriptor);
2682 /* Return an expression for the base offset of an array. */
2684 tree
2685 gfc_conv_array_offset (tree descriptor)
2687 tree type;
2689 type = TREE_TYPE (descriptor);
2690 if (GFC_ARRAY_TYPE_P (type))
2691 return GFC_TYPE_ARRAY_OFFSET (type);
2692 else
2693 return gfc_conv_descriptor_offset_get (descriptor);
2697 /* Get an expression for the array stride. */
2699 tree
2700 gfc_conv_array_stride (tree descriptor, int dim)
2702 tree tmp;
2703 tree type;
2705 type = TREE_TYPE (descriptor);
2707 /* For descriptorless arrays use the array size. */
2708 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2709 if (tmp != NULL_TREE)
2710 return tmp;
2712 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2713 return tmp;
2717 /* Like gfc_conv_array_stride, but for the lower bound. */
2719 tree
2720 gfc_conv_array_lbound (tree descriptor, int dim)
2722 tree tmp;
2723 tree type;
2725 type = TREE_TYPE (descriptor);
2727 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2728 if (tmp != NULL_TREE)
2729 return tmp;
2731 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2732 return tmp;
2736 /* Like gfc_conv_array_stride, but for the upper bound. */
2738 tree
2739 gfc_conv_array_ubound (tree descriptor, int dim)
2741 tree tmp;
2742 tree type;
2744 type = TREE_TYPE (descriptor);
2746 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2747 if (tmp != NULL_TREE)
2748 return tmp;
2750 /* This should only ever happen when passing an assumed shape array
2751 as an actual parameter. The value will never be used. */
2752 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2753 return gfc_index_zero_node;
2755 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2756 return tmp;
2760 /* Generate code to perform an array index bound check. */
2762 static tree
2763 trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n,
2764 locus * where, bool check_upper)
2766 tree fault;
2767 tree tmp_lo, tmp_up;
2768 tree descriptor;
2769 char *msg;
2770 const char * name = NULL;
2772 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2773 return index;
2775 descriptor = ss->info->data.array.descriptor;
2777 index = gfc_evaluate_now (index, &se->pre);
2779 /* We find a name for the error message. */
2780 name = ss->info->expr->symtree->n.sym->name;
2781 gcc_assert (name != NULL);
2783 if (TREE_CODE (descriptor) == VAR_DECL)
2784 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
2786 /* If upper bound is present, include both bounds in the error message. */
2787 if (check_upper)
2789 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2790 tmp_up = gfc_conv_array_ubound (descriptor, n);
2792 if (name)
2793 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2794 "outside of expected range (%%ld:%%ld)", n+1, name);
2795 else
2796 asprintf (&msg, "Index '%%ld' of dimension %d "
2797 "outside of expected range (%%ld:%%ld)", n+1);
2799 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2800 index, tmp_lo);
2801 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2802 fold_convert (long_integer_type_node, index),
2803 fold_convert (long_integer_type_node, tmp_lo),
2804 fold_convert (long_integer_type_node, tmp_up));
2805 fault = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2806 index, tmp_up);
2807 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2808 fold_convert (long_integer_type_node, index),
2809 fold_convert (long_integer_type_node, tmp_lo),
2810 fold_convert (long_integer_type_node, tmp_up));
2811 free (msg);
2813 else
2815 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2817 if (name)
2818 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2819 "below lower bound of %%ld", n+1, name);
2820 else
2821 asprintf (&msg, "Index '%%ld' of dimension %d "
2822 "below lower bound of %%ld", n+1);
2824 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2825 index, tmp_lo);
2826 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2827 fold_convert (long_integer_type_node, index),
2828 fold_convert (long_integer_type_node, tmp_lo));
2829 free (msg);
2832 return index;
2836 /* Return the offset for an index. Performs bound checking for elemental
2837 dimensions. Single element references are processed separately.
2838 DIM is the array dimension, I is the loop dimension. */
2840 static tree
2841 conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
2842 gfc_array_ref * ar, tree stride)
2844 gfc_array_info *info;
2845 tree index;
2846 tree desc;
2847 tree data;
2849 info = &ss->info->data.array;
2851 /* Get the index into the array for this dimension. */
2852 if (ar)
2854 gcc_assert (ar->type != AR_ELEMENT);
2855 switch (ar->dimen_type[dim])
2857 case DIMEN_THIS_IMAGE:
2858 gcc_unreachable ();
2859 break;
2860 case DIMEN_ELEMENT:
2861 /* Elemental dimension. */
2862 gcc_assert (info->subscript[dim]
2863 && info->subscript[dim]->info->type == GFC_SS_SCALAR);
2864 /* We've already translated this value outside the loop. */
2865 index = info->subscript[dim]->info->data.scalar.value;
2867 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2868 ar->as->type != AS_ASSUMED_SIZE
2869 || dim < ar->dimen - 1);
2870 break;
2872 case DIMEN_VECTOR:
2873 gcc_assert (info && se->loop);
2874 gcc_assert (info->subscript[dim]
2875 && info->subscript[dim]->info->type == GFC_SS_VECTOR);
2876 desc = info->subscript[dim]->info->data.array.descriptor;
2878 /* Get a zero-based index into the vector. */
2879 index = fold_build2_loc (input_location, MINUS_EXPR,
2880 gfc_array_index_type,
2881 se->loop->loopvar[i], se->loop->from[i]);
2883 /* Multiply the index by the stride. */
2884 index = fold_build2_loc (input_location, MULT_EXPR,
2885 gfc_array_index_type,
2886 index, gfc_conv_array_stride (desc, 0));
2888 /* Read the vector to get an index into info->descriptor. */
2889 data = build_fold_indirect_ref_loc (input_location,
2890 gfc_conv_array_data (desc));
2891 index = gfc_build_array_ref (data, index, NULL);
2892 index = gfc_evaluate_now (index, &se->pre);
2893 index = fold_convert (gfc_array_index_type, index);
2895 /* Do any bounds checking on the final info->descriptor index. */
2896 index = trans_array_bound_check (se, ss, index, dim, &ar->where,
2897 ar->as->type != AS_ASSUMED_SIZE
2898 || dim < ar->dimen - 1);
2899 break;
2901 case DIMEN_RANGE:
2902 /* Scalarized dimension. */
2903 gcc_assert (info && se->loop);
2905 /* Multiply the loop variable by the stride and delta. */
2906 index = se->loop->loopvar[i];
2907 if (!integer_onep (info->stride[dim]))
2908 index = fold_build2_loc (input_location, MULT_EXPR,
2909 gfc_array_index_type, index,
2910 info->stride[dim]);
2911 if (!integer_zerop (info->delta[dim]))
2912 index = fold_build2_loc (input_location, PLUS_EXPR,
2913 gfc_array_index_type, index,
2914 info->delta[dim]);
2915 break;
2917 default:
2918 gcc_unreachable ();
2921 else
2923 /* Temporary array or derived type component. */
2924 gcc_assert (se->loop);
2925 index = se->loop->loopvar[se->loop->order[i]];
2927 /* Pointer functions can have stride[0] different from unity.
2928 Use the stride returned by the function call and stored in
2929 the descriptor for the temporary. */
2930 if (se->ss && se->ss->info->type == GFC_SS_FUNCTION
2931 && se->ss->info->expr
2932 && se->ss->info->expr->symtree
2933 && se->ss->info->expr->symtree->n.sym->result
2934 && se->ss->info->expr->symtree->n.sym->result->attr.pointer)
2935 stride = gfc_conv_descriptor_stride_get (info->descriptor,
2936 gfc_rank_cst[dim]);
2938 if (!integer_zerop (info->delta[dim]))
2939 index = fold_build2_loc (input_location, PLUS_EXPR,
2940 gfc_array_index_type, index, info->delta[dim]);
2943 /* Multiply by the stride. */
2944 if (!integer_onep (stride))
2945 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2946 index, stride);
2948 return index;
2952 /* Build a scalarized array reference using the vptr 'size'. */
2954 static bool
2955 build_class_array_ref (gfc_se *se, tree base, tree index)
2957 tree type;
2958 tree size;
2959 tree offset;
2960 tree decl;
2961 tree tmp;
2962 gfc_expr *expr = se->ss->info->expr;
2963 gfc_ref *ref;
2964 gfc_ref *class_ref;
2965 gfc_typespec *ts;
2967 if (expr == NULL || expr->ts.type != BT_CLASS)
2968 return false;
2970 if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS)
2971 ts = &expr->symtree->n.sym->ts;
2972 else
2973 ts = NULL;
2974 class_ref = NULL;
2976 for (ref = expr->ref; ref; ref = ref->next)
2978 if (ref->type == REF_COMPONENT
2979 && ref->u.c.component->ts.type == BT_CLASS
2980 && ref->next && ref->next->type == REF_COMPONENT
2981 && strcmp (ref->next->u.c.component->name, "_data") == 0
2982 && ref->next->next
2983 && ref->next->next->type == REF_ARRAY
2984 && ref->next->next->u.ar.type != AR_ELEMENT)
2986 ts = &ref->u.c.component->ts;
2987 class_ref = ref;
2988 break;
2992 if (ts == NULL)
2993 return false;
2995 if (class_ref == NULL)
2996 decl = expr->symtree->n.sym->backend_decl;
2997 else
2999 /* Remove everything after the last class reference, convert the
3000 expression and then recover its tailend once more. */
3001 gfc_se tmpse;
3002 ref = class_ref->next;
3003 class_ref->next = NULL;
3004 gfc_init_se (&tmpse, NULL);
3005 gfc_conv_expr (&tmpse, expr);
3006 decl = tmpse.expr;
3007 class_ref->next = ref;
3010 size = gfc_vtable_size_get (decl);
3012 /* Build the address of the element. */
3013 type = TREE_TYPE (TREE_TYPE (base));
3014 size = fold_convert (TREE_TYPE (index), size);
3015 offset = fold_build2_loc (input_location, MULT_EXPR,
3016 gfc_array_index_type,
3017 index, size);
3018 tmp = gfc_build_addr_expr (pvoid_type_node, base);
3019 tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
3020 tmp = fold_convert (build_pointer_type (type), tmp);
3022 /* Return the element in the se expression. */
3023 se->expr = build_fold_indirect_ref_loc (input_location, tmp);
3024 return true;
3028 /* Build a scalarized reference to an array. */
3030 static void
3031 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
3033 gfc_array_info *info;
3034 tree decl = NULL_TREE;
3035 tree index;
3036 tree tmp;
3037 gfc_ss *ss;
3038 gfc_expr *expr;
3039 int n;
3041 ss = se->ss;
3042 expr = ss->info->expr;
3043 info = &ss->info->data.array;
3044 if (ar)
3045 n = se->loop->order[0];
3046 else
3047 n = 0;
3049 index = conv_array_index_offset (se, ss, ss->dim[n], n, ar, info->stride0);
3050 /* Add the offset for this dimension to the stored offset for all other
3051 dimensions. */
3052 if (!integer_zerop (info->offset))
3053 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3054 index, info->offset);
3056 if (expr && is_subref_array (expr))
3057 decl = expr->symtree->n.sym->backend_decl;
3059 tmp = build_fold_indirect_ref_loc (input_location, info->data);
3061 /* Use the vptr 'size' field to access a class the element of a class
3062 array. */
3063 if (build_class_array_ref (se, tmp, index))
3064 return;
3066 se->expr = gfc_build_array_ref (tmp, index, decl);
3070 /* Translate access of temporary array. */
3072 void
3073 gfc_conv_tmp_array_ref (gfc_se * se)
3075 se->string_length = se->ss->info->string_length;
3076 gfc_conv_scalarized_array_ref (se, NULL);
3077 gfc_advance_se_ss_chain (se);
3080 /* Add T to the offset pair *OFFSET, *CST_OFFSET. */
3082 static void
3083 add_to_offset (tree *cst_offset, tree *offset, tree t)
3085 if (TREE_CODE (t) == INTEGER_CST)
3086 *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
3087 else
3089 if (!integer_zerop (*offset))
3090 *offset = fold_build2_loc (input_location, PLUS_EXPR,
3091 gfc_array_index_type, *offset, t);
3092 else
3093 *offset = t;
3098 static tree
3099 build_array_ref (tree desc, tree offset, tree decl)
3101 tree tmp;
3103 /* Class array references need special treatment because the assigned
3104 type size needs to be used to point to the element. */
3105 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
3106 && TREE_CODE (desc) == COMPONENT_REF
3107 && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
3109 tree type = gfc_get_element_type (TREE_TYPE (desc));
3110 tmp = TREE_OPERAND (desc, 0);
3111 tmp = gfc_get_class_array_ref (offset, tmp);
3112 tmp = fold_convert (build_pointer_type (type), tmp);
3113 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3115 else
3117 tmp = gfc_conv_array_data (desc);
3118 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3119 tmp = gfc_build_array_ref (tmp, offset, decl);
3122 return tmp;
3127 /* Build an array reference. se->expr already holds the array descriptor.
3128 This should be either a variable, indirect variable reference or component
3129 reference. For arrays which do not have a descriptor, se->expr will be
3130 the data pointer.
3131 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
3133 void
3134 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
3135 locus * where)
3137 int n;
3138 tree offset, cst_offset;
3139 tree tmp;
3140 tree stride;
3141 gfc_se indexse;
3142 gfc_se tmpse;
3144 if (ar->dimen == 0)
3146 gcc_assert (ar->codimen);
3148 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
3149 se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
3150 else
3152 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
3153 && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
3154 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
3156 /* Use the actual tree type and not the wrapped coarray. */
3157 if (!se->want_pointer)
3158 se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
3159 se->expr);
3162 return;
3165 /* Handle scalarized references separately. */
3166 if (ar->type != AR_ELEMENT)
3168 gfc_conv_scalarized_array_ref (se, ar);
3169 gfc_advance_se_ss_chain (se);
3170 return;
3173 cst_offset = offset = gfc_index_zero_node;
3174 add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (se->expr));
3176 /* Calculate the offsets from all the dimensions. Make sure to associate
3177 the final offset so that we form a chain of loop invariant summands. */
3178 for (n = ar->dimen - 1; n >= 0; n--)
3180 /* Calculate the index for this dimension. */
3181 gfc_init_se (&indexse, se);
3182 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
3183 gfc_add_block_to_block (&se->pre, &indexse.pre);
3185 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3187 /* Check array bounds. */
3188 tree cond;
3189 char *msg;
3191 /* Evaluate the indexse.expr only once. */
3192 indexse.expr = save_expr (indexse.expr);
3194 /* Lower bound. */
3195 tmp = gfc_conv_array_lbound (se->expr, n);
3196 if (sym->attr.temporary)
3198 gfc_init_se (&tmpse, se);
3199 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
3200 gfc_array_index_type);
3201 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3202 tmp = tmpse.expr;
3205 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
3206 indexse.expr, tmp);
3207 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3208 "below lower bound of %%ld", n+1, sym->name);
3209 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3210 fold_convert (long_integer_type_node,
3211 indexse.expr),
3212 fold_convert (long_integer_type_node, tmp));
3213 free (msg);
3215 /* Upper bound, but not for the last dimension of assumed-size
3216 arrays. */
3217 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
3219 tmp = gfc_conv_array_ubound (se->expr, n);
3220 if (sym->attr.temporary)
3222 gfc_init_se (&tmpse, se);
3223 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
3224 gfc_array_index_type);
3225 gfc_add_block_to_block (&se->pre, &tmpse.pre);
3226 tmp = tmpse.expr;
3229 cond = fold_build2_loc (input_location, GT_EXPR,
3230 boolean_type_node, indexse.expr, tmp);
3231 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3232 "above upper bound of %%ld", n+1, sym->name);
3233 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
3234 fold_convert (long_integer_type_node,
3235 indexse.expr),
3236 fold_convert (long_integer_type_node, tmp));
3237 free (msg);
3241 /* Multiply the index by the stride. */
3242 stride = gfc_conv_array_stride (se->expr, n);
3243 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3244 indexse.expr, stride);
3246 /* And add it to the total. */
3247 add_to_offset (&cst_offset, &offset, tmp);
3250 if (!integer_zerop (cst_offset))
3251 offset = fold_build2_loc (input_location, PLUS_EXPR,
3252 gfc_array_index_type, offset, cst_offset);
3254 se->expr = build_array_ref (se->expr, offset, sym->backend_decl);
3258 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
3259 LOOP_DIM dimension (if any) to array's offset. */
3261 static void
3262 add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
3263 gfc_array_ref *ar, int array_dim, int loop_dim)
3265 gfc_se se;
3266 gfc_array_info *info;
3267 tree stride, index;
3269 info = &ss->info->data.array;
3271 gfc_init_se (&se, NULL);
3272 se.loop = loop;
3273 se.expr = info->descriptor;
3274 stride = gfc_conv_array_stride (info->descriptor, array_dim);
3275 index = conv_array_index_offset (&se, ss, array_dim, loop_dim, ar, stride);
3276 gfc_add_block_to_block (pblock, &se.pre);
3278 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
3279 gfc_array_index_type,
3280 info->offset, index);
3281 info->offset = gfc_evaluate_now (info->offset, pblock);
3285 /* Generate the code to be executed immediately before entering a
3286 scalarization loop. */
3288 static void
3289 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
3290 stmtblock_t * pblock)
3292 tree stride;
3293 gfc_ss_info *ss_info;
3294 gfc_array_info *info;
3295 gfc_ss_type ss_type;
3296 gfc_ss *ss, *pss;
3297 gfc_loopinfo *ploop;
3298 gfc_array_ref *ar;
3299 int i;
3301 /* This code will be executed before entering the scalarization loop
3302 for this dimension. */
3303 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3305 ss_info = ss->info;
3307 if ((ss_info->useflags & flag) == 0)
3308 continue;
3310 ss_type = ss_info->type;
3311 if (ss_type != GFC_SS_SECTION
3312 && ss_type != GFC_SS_FUNCTION
3313 && ss_type != GFC_SS_CONSTRUCTOR
3314 && ss_type != GFC_SS_COMPONENT)
3315 continue;
3317 info = &ss_info->data.array;
3319 gcc_assert (dim < ss->dimen);
3320 gcc_assert (ss->dimen == loop->dimen);
3322 if (info->ref)
3323 ar = &info->ref->u.ar;
3324 else
3325 ar = NULL;
3327 if (dim == loop->dimen - 1 && loop->parent != NULL)
3329 /* If we are in the outermost dimension of this loop, the previous
3330 dimension shall be in the parent loop. */
3331 gcc_assert (ss->parent != NULL);
3333 pss = ss->parent;
3334 ploop = loop->parent;
3336 /* ss and ss->parent are about the same array. */
3337 gcc_assert (ss_info == pss->info);
3339 else
3341 ploop = loop;
3342 pss = ss;
3345 if (dim == loop->dimen - 1)
3346 i = 0;
3347 else
3348 i = dim + 1;
3350 /* For the time being, there is no loop reordering. */
3351 gcc_assert (i == ploop->order[i]);
3352 i = ploop->order[i];
3354 if (dim == loop->dimen - 1 && loop->parent == NULL)
3356 stride = gfc_conv_array_stride (info->descriptor,
3357 innermost_ss (ss)->dim[i]);
3359 /* Calculate the stride of the innermost loop. Hopefully this will
3360 allow the backend optimizers to do their stuff more effectively.
3362 info->stride0 = gfc_evaluate_now (stride, pblock);
3364 /* For the outermost loop calculate the offset due to any
3365 elemental dimensions. It will have been initialized with the
3366 base offset of the array. */
3367 if (info->ref)
3369 for (i = 0; i < ar->dimen; i++)
3371 if (ar->dimen_type[i] != DIMEN_ELEMENT)
3372 continue;
3374 add_array_offset (pblock, loop, ss, ar, i, /* unused */ -1);
3378 else
3379 /* Add the offset for the previous loop dimension. */
3380 add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
3382 /* Remember this offset for the second loop. */
3383 if (dim == loop->temp_dim - 1 && loop->parent == NULL)
3384 info->saved_offset = info->offset;
3389 /* Start a scalarized expression. Creates a scope and declares loop
3390 variables. */
3392 void
3393 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
3395 int dim;
3396 int n;
3397 int flags;
3399 gcc_assert (!loop->array_parameter);
3401 for (dim = loop->dimen - 1; dim >= 0; dim--)
3403 n = loop->order[dim];
3405 gfc_start_block (&loop->code[n]);
3407 /* Create the loop variable. */
3408 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
3410 if (dim < loop->temp_dim)
3411 flags = 3;
3412 else
3413 flags = 1;
3414 /* Calculate values that will be constant within this loop. */
3415 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
3417 gfc_start_block (pbody);
3421 /* Generates the actual loop code for a scalarization loop. */
3423 void
3424 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
3425 stmtblock_t * pbody)
3427 stmtblock_t block;
3428 tree cond;
3429 tree tmp;
3430 tree loopbody;
3431 tree exit_label;
3432 tree stmt;
3433 tree init;
3434 tree incr;
3436 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
3437 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
3438 && n == loop->dimen - 1)
3440 /* We create an OMP_FOR construct for the outermost scalarized loop. */
3441 init = make_tree_vec (1);
3442 cond = make_tree_vec (1);
3443 incr = make_tree_vec (1);
3445 /* Cycle statement is implemented with a goto. Exit statement must not
3446 be present for this loop. */
3447 exit_label = gfc_build_label_decl (NULL_TREE);
3448 TREE_USED (exit_label) = 1;
3450 /* Label for cycle statements (if needed). */
3451 tmp = build1_v (LABEL_EXPR, exit_label);
3452 gfc_add_expr_to_block (pbody, tmp);
3454 stmt = make_node (OMP_FOR);
3456 TREE_TYPE (stmt) = void_type_node;
3457 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
3459 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
3460 OMP_CLAUSE_SCHEDULE);
3461 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
3462 = OMP_CLAUSE_SCHEDULE_STATIC;
3463 if (ompws_flags & OMPWS_NOWAIT)
3464 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
3465 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
3467 /* Initialize the loopvar. */
3468 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
3469 loop->from[n]);
3470 OMP_FOR_INIT (stmt) = init;
3471 /* The exit condition. */
3472 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
3473 boolean_type_node,
3474 loop->loopvar[n], loop->to[n]);
3475 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
3476 OMP_FOR_COND (stmt) = cond;
3477 /* Increment the loopvar. */
3478 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3479 loop->loopvar[n], gfc_index_one_node);
3480 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
3481 void_type_node, loop->loopvar[n], tmp);
3482 OMP_FOR_INCR (stmt) = incr;
3484 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
3485 gfc_add_expr_to_block (&loop->code[n], stmt);
3487 else
3489 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
3490 && (loop->temp_ss == NULL);
3492 loopbody = gfc_finish_block (pbody);
3494 if (reverse_loop)
3496 tmp = loop->from[n];
3497 loop->from[n] = loop->to[n];
3498 loop->to[n] = tmp;
3501 /* Initialize the loopvar. */
3502 if (loop->loopvar[n] != loop->from[n])
3503 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
3505 exit_label = gfc_build_label_decl (NULL_TREE);
3507 /* Generate the loop body. */
3508 gfc_init_block (&block);
3510 /* The exit condition. */
3511 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
3512 boolean_type_node, loop->loopvar[n], loop->to[n]);
3513 tmp = build1_v (GOTO_EXPR, exit_label);
3514 TREE_USED (exit_label) = 1;
3515 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
3516 gfc_add_expr_to_block (&block, tmp);
3518 /* The main body. */
3519 gfc_add_expr_to_block (&block, loopbody);
3521 /* Increment the loopvar. */
3522 tmp = fold_build2_loc (input_location,
3523 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
3524 gfc_array_index_type, loop->loopvar[n],
3525 gfc_index_one_node);
3527 gfc_add_modify (&block, loop->loopvar[n], tmp);
3529 /* Build the loop. */
3530 tmp = gfc_finish_block (&block);
3531 tmp = build1_v (LOOP_EXPR, tmp);
3532 gfc_add_expr_to_block (&loop->code[n], tmp);
3534 /* Add the exit label. */
3535 tmp = build1_v (LABEL_EXPR, exit_label);
3536 gfc_add_expr_to_block (&loop->code[n], tmp);
3542 /* Finishes and generates the loops for a scalarized expression. */
3544 void
3545 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
3547 int dim;
3548 int n;
3549 gfc_ss *ss;
3550 stmtblock_t *pblock;
3551 tree tmp;
3553 pblock = body;
3554 /* Generate the loops. */
3555 for (dim = 0; dim < loop->dimen; dim++)
3557 n = loop->order[dim];
3558 gfc_trans_scalarized_loop_end (loop, n, pblock);
3559 loop->loopvar[n] = NULL_TREE;
3560 pblock = &loop->code[n];
3563 tmp = gfc_finish_block (pblock);
3564 gfc_add_expr_to_block (&loop->pre, tmp);
3566 /* Clear all the used flags. */
3567 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3568 if (ss->parent == NULL)
3569 ss->info->useflags = 0;
3573 /* Finish the main body of a scalarized expression, and start the secondary
3574 copying body. */
3576 void
3577 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
3579 int dim;
3580 int n;
3581 stmtblock_t *pblock;
3582 gfc_ss *ss;
3584 pblock = body;
3585 /* We finish as many loops as are used by the temporary. */
3586 for (dim = 0; dim < loop->temp_dim - 1; dim++)
3588 n = loop->order[dim];
3589 gfc_trans_scalarized_loop_end (loop, n, pblock);
3590 loop->loopvar[n] = NULL_TREE;
3591 pblock = &loop->code[n];
3594 /* We don't want to finish the outermost loop entirely. */
3595 n = loop->order[loop->temp_dim - 1];
3596 gfc_trans_scalarized_loop_end (loop, n, pblock);
3598 /* Restore the initial offsets. */
3599 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3601 gfc_ss_type ss_type;
3602 gfc_ss_info *ss_info;
3604 ss_info = ss->info;
3606 if ((ss_info->useflags & 2) == 0)
3607 continue;
3609 ss_type = ss_info->type;
3610 if (ss_type != GFC_SS_SECTION
3611 && ss_type != GFC_SS_FUNCTION
3612 && ss_type != GFC_SS_CONSTRUCTOR
3613 && ss_type != GFC_SS_COMPONENT)
3614 continue;
3616 ss_info->data.array.offset = ss_info->data.array.saved_offset;
3619 /* Restart all the inner loops we just finished. */
3620 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
3622 n = loop->order[dim];
3624 gfc_start_block (&loop->code[n]);
3626 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
3628 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
3631 /* Start a block for the secondary copying code. */
3632 gfc_start_block (body);
3636 /* Precalculate (either lower or upper) bound of an array section.
3637 BLOCK: Block in which the (pre)calculation code will go.
3638 BOUNDS[DIM]: Where the bound value will be stored once evaluated.
3639 VALUES[DIM]: Specified bound (NULL <=> unspecified).
3640 DESC: Array descriptor from which the bound will be picked if unspecified
3641 (either lower or upper bound according to LBOUND). */
3643 static void
3644 evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
3645 tree desc, int dim, bool lbound)
3647 gfc_se se;
3648 gfc_expr * input_val = values[dim];
3649 tree *output = &bounds[dim];
3652 if (input_val)
3654 /* Specified section bound. */
3655 gfc_init_se (&se, NULL);
3656 gfc_conv_expr_type (&se, input_val, gfc_array_index_type);
3657 gfc_add_block_to_block (block, &se.pre);
3658 *output = se.expr;
3660 else
3662 /* No specific bound specified so use the bound of the array. */
3663 *output = lbound ? gfc_conv_array_lbound (desc, dim) :
3664 gfc_conv_array_ubound (desc, dim);
3666 *output = gfc_evaluate_now (*output, block);
3670 /* Calculate the lower bound of an array section. */
3672 static void
3673 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
3675 gfc_expr *stride = NULL;
3676 tree desc;
3677 gfc_se se;
3678 gfc_array_info *info;
3679 gfc_array_ref *ar;
3681 gcc_assert (ss->info->type == GFC_SS_SECTION);
3683 info = &ss->info->data.array;
3684 ar = &info->ref->u.ar;
3686 if (ar->dimen_type[dim] == DIMEN_VECTOR)
3688 /* We use a zero-based index to access the vector. */
3689 info->start[dim] = gfc_index_zero_node;
3690 info->end[dim] = NULL;
3691 info->stride[dim] = gfc_index_one_node;
3692 return;
3695 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE
3696 || ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
3697 desc = info->descriptor;
3698 stride = ar->stride[dim];
3700 /* Calculate the start of the range. For vector subscripts this will
3701 be the range of the vector. */
3702 evaluate_bound (&loop->pre, info->start, ar->start, desc, dim, true);
3704 /* Similarly calculate the end. Although this is not used in the
3705 scalarizer, it is needed when checking bounds and where the end
3706 is an expression with side-effects. */
3707 evaluate_bound (&loop->pre, info->end, ar->end, desc, dim, false);
3709 /* Calculate the stride. */
3710 if (stride == NULL)
3711 info->stride[dim] = gfc_index_one_node;
3712 else
3714 gfc_init_se (&se, NULL);
3715 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3716 gfc_add_block_to_block (&loop->pre, &se.pre);
3717 info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre);
3722 /* Calculates the range start and stride for a SS chain. Also gets the
3723 descriptor and data pointer. The range of vector subscripts is the size
3724 of the vector. Array bounds are also checked. */
3726 void
3727 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3729 int n;
3730 tree tmp;
3731 gfc_ss *ss;
3732 tree desc;
3734 loop->dimen = 0;
3735 /* Determine the rank of the loop. */
3736 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3738 switch (ss->info->type)
3740 case GFC_SS_SECTION:
3741 case GFC_SS_CONSTRUCTOR:
3742 case GFC_SS_FUNCTION:
3743 case GFC_SS_COMPONENT:
3744 loop->dimen = ss->dimen;
3745 goto done;
3747 /* As usual, lbound and ubound are exceptions!. */
3748 case GFC_SS_INTRINSIC:
3749 switch (ss->info->expr->value.function.isym->id)
3751 case GFC_ISYM_LBOUND:
3752 case GFC_ISYM_UBOUND:
3753 case GFC_ISYM_LCOBOUND:
3754 case GFC_ISYM_UCOBOUND:
3755 case GFC_ISYM_THIS_IMAGE:
3756 loop->dimen = ss->dimen;
3757 goto done;
3759 default:
3760 break;
3763 default:
3764 break;
3768 /* We should have determined the rank of the expression by now. If
3769 not, that's bad news. */
3770 gcc_unreachable ();
3772 done:
3773 /* Loop over all the SS in the chain. */
3774 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3776 gfc_ss_info *ss_info;
3777 gfc_array_info *info;
3778 gfc_expr *expr;
3780 ss_info = ss->info;
3781 expr = ss_info->expr;
3782 info = &ss_info->data.array;
3784 if (expr && expr->shape && !info->shape)
3785 info->shape = expr->shape;
3787 switch (ss_info->type)
3789 case GFC_SS_SECTION:
3790 /* Get the descriptor for the array. If it is a cross loops array,
3791 we got the descriptor already in the outermost loop. */
3792 if (ss->parent == NULL)
3793 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
3795 for (n = 0; n < ss->dimen; n++)
3796 gfc_conv_section_startstride (loop, ss, ss->dim[n]);
3797 break;
3799 case GFC_SS_INTRINSIC:
3800 switch (expr->value.function.isym->id)
3802 /* Fall through to supply start and stride. */
3803 case GFC_ISYM_LBOUND:
3804 case GFC_ISYM_UBOUND:
3806 gfc_expr *arg;
3808 /* This is the variant without DIM=... */
3809 gcc_assert (expr->value.function.actual->next->expr == NULL);
3811 arg = expr->value.function.actual->expr;
3812 if (arg->rank == -1)
3814 gfc_se se;
3815 tree rank, tmp;
3817 /* The rank (hence the return value's shape) is unknown,
3818 we have to retrieve it. */
3819 gfc_init_se (&se, NULL);
3820 se.descriptor_only = 1;
3821 gfc_conv_expr (&se, arg);
3822 /* This is a bare variable, so there is no preliminary
3823 or cleanup code. */
3824 gcc_assert (se.pre.head == NULL_TREE
3825 && se.post.head == NULL_TREE);
3826 rank = gfc_conv_descriptor_rank (se.expr);
3827 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3828 gfc_array_index_type,
3829 fold_convert (gfc_array_index_type,
3830 rank),
3831 gfc_index_one_node);
3832 info->end[0] = gfc_evaluate_now (tmp, &loop->pre);
3833 info->start[0] = gfc_index_zero_node;
3834 info->stride[0] = gfc_index_one_node;
3835 continue;
3837 /* Otherwise fall through GFC_SS_FUNCTION. */
3839 case GFC_ISYM_LCOBOUND:
3840 case GFC_ISYM_UCOBOUND:
3841 case GFC_ISYM_THIS_IMAGE:
3842 break;
3844 default:
3845 continue;
3848 case GFC_SS_CONSTRUCTOR:
3849 case GFC_SS_FUNCTION:
3850 for (n = 0; n < ss->dimen; n++)
3852 int dim = ss->dim[n];
3854 info->start[dim] = gfc_index_zero_node;
3855 info->end[dim] = gfc_index_zero_node;
3856 info->stride[dim] = gfc_index_one_node;
3858 break;
3860 default:
3861 break;
3865 /* The rest is just runtime bound checking. */
3866 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3868 stmtblock_t block;
3869 tree lbound, ubound;
3870 tree end;
3871 tree size[GFC_MAX_DIMENSIONS];
3872 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
3873 gfc_array_info *info;
3874 char *msg;
3875 int dim;
3877 gfc_start_block (&block);
3879 for (n = 0; n < loop->dimen; n++)
3880 size[n] = NULL_TREE;
3882 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3884 stmtblock_t inner;
3885 gfc_ss_info *ss_info;
3886 gfc_expr *expr;
3887 locus *expr_loc;
3888 const char *expr_name;
3890 ss_info = ss->info;
3891 if (ss_info->type != GFC_SS_SECTION)
3892 continue;
3894 /* Catch allocatable lhs in f2003. */
3895 if (gfc_option.flag_realloc_lhs && ss->is_alloc_lhs)
3896 continue;
3898 expr = ss_info->expr;
3899 expr_loc = &expr->where;
3900 expr_name = expr->symtree->name;
3902 gfc_start_block (&inner);
3904 /* TODO: range checking for mapped dimensions. */
3905 info = &ss_info->data.array;
3907 /* This code only checks ranges. Elemental and vector
3908 dimensions are checked later. */
3909 for (n = 0; n < loop->dimen; n++)
3911 bool check_upper;
3913 dim = ss->dim[n];
3914 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
3915 continue;
3917 if (dim == info->ref->u.ar.dimen - 1
3918 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
3919 check_upper = false;
3920 else
3921 check_upper = true;
3923 /* Zero stride is not allowed. */
3924 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
3925 info->stride[dim], gfc_index_zero_node);
3926 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
3927 "of array '%s'", dim + 1, expr_name);
3928 gfc_trans_runtime_check (true, false, tmp, &inner,
3929 expr_loc, msg);
3930 free (msg);
3932 desc = info->descriptor;
3934 /* This is the run-time equivalent of resolve.c's
3935 check_dimension(). The logical is more readable there
3936 than it is here, with all the trees. */
3937 lbound = gfc_conv_array_lbound (desc, dim);
3938 end = info->end[dim];
3939 if (check_upper)
3940 ubound = gfc_conv_array_ubound (desc, dim);
3941 else
3942 ubound = NULL;
3944 /* non_zerosized is true when the selected range is not
3945 empty. */
3946 stride_pos = fold_build2_loc (input_location, GT_EXPR,
3947 boolean_type_node, info->stride[dim],
3948 gfc_index_zero_node);
3949 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3950 info->start[dim], end);
3951 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3952 boolean_type_node, stride_pos, tmp);
3954 stride_neg = fold_build2_loc (input_location, LT_EXPR,
3955 boolean_type_node,
3956 info->stride[dim], gfc_index_zero_node);
3957 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
3958 info->start[dim], end);
3959 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3960 boolean_type_node,
3961 stride_neg, tmp);
3962 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3963 boolean_type_node,
3964 stride_pos, stride_neg);
3966 /* Check the start of the range against the lower and upper
3967 bounds of the array, if the range is not empty.
3968 If upper bound is present, include both bounds in the
3969 error message. */
3970 if (check_upper)
3972 tmp = fold_build2_loc (input_location, LT_EXPR,
3973 boolean_type_node,
3974 info->start[dim], lbound);
3975 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3976 boolean_type_node,
3977 non_zerosized, tmp);
3978 tmp2 = fold_build2_loc (input_location, GT_EXPR,
3979 boolean_type_node,
3980 info->start[dim], ubound);
3981 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3982 boolean_type_node,
3983 non_zerosized, tmp2);
3984 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3985 "outside of expected range (%%ld:%%ld)",
3986 dim + 1, expr_name);
3987 gfc_trans_runtime_check (true, false, tmp, &inner,
3988 expr_loc, msg,
3989 fold_convert (long_integer_type_node, info->start[dim]),
3990 fold_convert (long_integer_type_node, lbound),
3991 fold_convert (long_integer_type_node, ubound));
3992 gfc_trans_runtime_check (true, false, tmp2, &inner,
3993 expr_loc, msg,
3994 fold_convert (long_integer_type_node, info->start[dim]),
3995 fold_convert (long_integer_type_node, lbound),
3996 fold_convert (long_integer_type_node, ubound));
3997 free (msg);
3999 else
4001 tmp = fold_build2_loc (input_location, LT_EXPR,
4002 boolean_type_node,
4003 info->start[dim], lbound);
4004 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4005 boolean_type_node, non_zerosized, tmp);
4006 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
4007 "below lower bound of %%ld",
4008 dim + 1, expr_name);
4009 gfc_trans_runtime_check (true, false, tmp, &inner,
4010 expr_loc, msg,
4011 fold_convert (long_integer_type_node, info->start[dim]),
4012 fold_convert (long_integer_type_node, lbound));
4013 free (msg);
4016 /* Compute the last element of the range, which is not
4017 necessarily "end" (think 0:5:3, which doesn't contain 5)
4018 and check it against both lower and upper bounds. */
4020 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4021 gfc_array_index_type, end,
4022 info->start[dim]);
4023 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
4024 gfc_array_index_type, tmp,
4025 info->stride[dim]);
4026 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4027 gfc_array_index_type, end, tmp);
4028 tmp2 = fold_build2_loc (input_location, LT_EXPR,
4029 boolean_type_node, tmp, lbound);
4030 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4031 boolean_type_node, non_zerosized, tmp2);
4032 if (check_upper)
4034 tmp3 = fold_build2_loc (input_location, GT_EXPR,
4035 boolean_type_node, tmp, ubound);
4036 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
4037 boolean_type_node, non_zerosized, tmp3);
4038 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
4039 "outside of expected range (%%ld:%%ld)",
4040 dim + 1, expr_name);
4041 gfc_trans_runtime_check (true, false, tmp2, &inner,
4042 expr_loc, msg,
4043 fold_convert (long_integer_type_node, tmp),
4044 fold_convert (long_integer_type_node, ubound),
4045 fold_convert (long_integer_type_node, lbound));
4046 gfc_trans_runtime_check (true, false, tmp3, &inner,
4047 expr_loc, msg,
4048 fold_convert (long_integer_type_node, tmp),
4049 fold_convert (long_integer_type_node, ubound),
4050 fold_convert (long_integer_type_node, lbound));
4051 free (msg);
4053 else
4055 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
4056 "below lower bound of %%ld",
4057 dim + 1, expr_name);
4058 gfc_trans_runtime_check (true, false, tmp2, &inner,
4059 expr_loc, msg,
4060 fold_convert (long_integer_type_node, tmp),
4061 fold_convert (long_integer_type_node, lbound));
4062 free (msg);
4065 /* Check the section sizes match. */
4066 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4067 gfc_array_index_type, end,
4068 info->start[dim]);
4069 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4070 gfc_array_index_type, tmp,
4071 info->stride[dim]);
4072 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4073 gfc_array_index_type,
4074 gfc_index_one_node, tmp);
4075 tmp = fold_build2_loc (input_location, MAX_EXPR,
4076 gfc_array_index_type, tmp,
4077 build_int_cst (gfc_array_index_type, 0));
4078 /* We remember the size of the first section, and check all the
4079 others against this. */
4080 if (size[n])
4082 tmp3 = fold_build2_loc (input_location, NE_EXPR,
4083 boolean_type_node, tmp, size[n]);
4084 asprintf (&msg, "Array bound mismatch for dimension %d "
4085 "of array '%s' (%%ld/%%ld)",
4086 dim + 1, expr_name);
4088 gfc_trans_runtime_check (true, false, tmp3, &inner,
4089 expr_loc, msg,
4090 fold_convert (long_integer_type_node, tmp),
4091 fold_convert (long_integer_type_node, size[n]));
4093 free (msg);
4095 else
4096 size[n] = gfc_evaluate_now (tmp, &inner);
4099 tmp = gfc_finish_block (&inner);
4101 /* For optional arguments, only check bounds if the argument is
4102 present. */
4103 if (expr->symtree->n.sym->attr.optional
4104 || expr->symtree->n.sym->attr.not_always_present)
4105 tmp = build3_v (COND_EXPR,
4106 gfc_conv_expr_present (expr->symtree->n.sym),
4107 tmp, build_empty_stmt (input_location));
4109 gfc_add_expr_to_block (&block, tmp);
4113 tmp = gfc_finish_block (&block);
4114 gfc_add_expr_to_block (&loop->pre, tmp);
4117 for (loop = loop->nested; loop; loop = loop->next)
4118 gfc_conv_ss_startstride (loop);
4121 /* Return true if both symbols could refer to the same data object. Does
4122 not take account of aliasing due to equivalence statements. */
4124 static int
4125 symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer,
4126 bool lsym_target, bool rsym_pointer, bool rsym_target)
4128 /* Aliasing isn't possible if the symbols have different base types. */
4129 if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0)
4130 return 0;
4132 /* Pointers can point to other pointers and target objects. */
4134 if ((lsym_pointer && (rsym_pointer || rsym_target))
4135 || (rsym_pointer && (lsym_pointer || lsym_target)))
4136 return 1;
4138 /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7
4139 and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already
4140 checked above. */
4141 if (lsym_target && rsym_target
4142 && ((lsym->attr.dummy && !lsym->attr.contiguous
4143 && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE))
4144 || (rsym->attr.dummy && !rsym->attr.contiguous
4145 && (!rsym->attr.dimension
4146 || rsym->as->type == AS_ASSUMED_SHAPE))))
4147 return 1;
4149 return 0;
4153 /* Return true if the two SS could be aliased, i.e. both point to the same data
4154 object. */
4155 /* TODO: resolve aliases based on frontend expressions. */
4157 static int
4158 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
4160 gfc_ref *lref;
4161 gfc_ref *rref;
4162 gfc_expr *lexpr, *rexpr;
4163 gfc_symbol *lsym;
4164 gfc_symbol *rsym;
4165 bool lsym_pointer, lsym_target, rsym_pointer, rsym_target;
4167 lexpr = lss->info->expr;
4168 rexpr = rss->info->expr;
4170 lsym = lexpr->symtree->n.sym;
4171 rsym = rexpr->symtree->n.sym;
4173 lsym_pointer = lsym->attr.pointer;
4174 lsym_target = lsym->attr.target;
4175 rsym_pointer = rsym->attr.pointer;
4176 rsym_target = rsym->attr.target;
4178 if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target,
4179 rsym_pointer, rsym_target))
4180 return 1;
4182 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
4183 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
4184 return 0;
4186 /* For derived types we must check all the component types. We can ignore
4187 array references as these will have the same base type as the previous
4188 component ref. */
4189 for (lref = lexpr->ref; lref != lss->info->data.array.ref; lref = lref->next)
4191 if (lref->type != REF_COMPONENT)
4192 continue;
4194 lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer;
4195 lsym_target = lsym_target || lref->u.c.sym->attr.target;
4197 if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target,
4198 rsym_pointer, rsym_target))
4199 return 1;
4201 if ((lsym_pointer && (rsym_pointer || rsym_target))
4202 || (rsym_pointer && (lsym_pointer || lsym_target)))
4204 if (gfc_compare_types (&lref->u.c.component->ts,
4205 &rsym->ts))
4206 return 1;
4209 for (rref = rexpr->ref; rref != rss->info->data.array.ref;
4210 rref = rref->next)
4212 if (rref->type != REF_COMPONENT)
4213 continue;
4215 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4216 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4218 if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym,
4219 lsym_pointer, lsym_target,
4220 rsym_pointer, rsym_target))
4221 return 1;
4223 if ((lsym_pointer && (rsym_pointer || rsym_target))
4224 || (rsym_pointer && (lsym_pointer || lsym_target)))
4226 if (gfc_compare_types (&lref->u.c.component->ts,
4227 &rref->u.c.sym->ts))
4228 return 1;
4229 if (gfc_compare_types (&lref->u.c.sym->ts,
4230 &rref->u.c.component->ts))
4231 return 1;
4232 if (gfc_compare_types (&lref->u.c.component->ts,
4233 &rref->u.c.component->ts))
4234 return 1;
4239 lsym_pointer = lsym->attr.pointer;
4240 lsym_target = lsym->attr.target;
4241 lsym_pointer = lsym->attr.pointer;
4242 lsym_target = lsym->attr.target;
4244 for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
4246 if (rref->type != REF_COMPONENT)
4247 break;
4249 rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer;
4250 rsym_target = lsym_target || rref->u.c.sym->attr.target;
4252 if (symbols_could_alias (rref->u.c.sym, lsym,
4253 lsym_pointer, lsym_target,
4254 rsym_pointer, rsym_target))
4255 return 1;
4257 if ((lsym_pointer && (rsym_pointer || rsym_target))
4258 || (rsym_pointer && (lsym_pointer || lsym_target)))
4260 if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts))
4261 return 1;
4265 return 0;
4269 /* Resolve array data dependencies. Creates a temporary if required. */
4270 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
4271 dependency.c. */
4273 void
4274 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
4275 gfc_ss * rss)
4277 gfc_ss *ss;
4278 gfc_ref *lref;
4279 gfc_ref *rref;
4280 gfc_expr *dest_expr;
4281 gfc_expr *ss_expr;
4282 int nDepend = 0;
4283 int i, j;
4285 loop->temp_ss = NULL;
4286 dest_expr = dest->info->expr;
4288 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
4290 if (ss->info->type != GFC_SS_SECTION)
4291 continue;
4293 ss_expr = ss->info->expr;
4295 if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym)
4297 if (gfc_could_be_alias (dest, ss)
4298 || gfc_are_equivalenced_arrays (dest_expr, ss_expr))
4300 nDepend = 1;
4301 break;
4304 else
4306 lref = dest_expr->ref;
4307 rref = ss_expr->ref;
4309 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
4311 if (nDepend == 1)
4312 break;
4314 for (i = 0; i < dest->dimen; i++)
4315 for (j = 0; j < ss->dimen; j++)
4316 if (i != j
4317 && dest->dim[i] == ss->dim[j])
4319 /* If we don't access array elements in the same order,
4320 there is a dependency. */
4321 nDepend = 1;
4322 goto temporary;
4324 #if 0
4325 /* TODO : loop shifting. */
4326 if (nDepend == 1)
4328 /* Mark the dimensions for LOOP SHIFTING */
4329 for (n = 0; n < loop->dimen; n++)
4331 int dim = dest->data.info.dim[n];
4333 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
4334 depends[n] = 2;
4335 else if (! gfc_is_same_range (&lref->u.ar,
4336 &rref->u.ar, dim, 0))
4337 depends[n] = 1;
4340 /* Put all the dimensions with dependencies in the
4341 innermost loops. */
4342 dim = 0;
4343 for (n = 0; n < loop->dimen; n++)
4345 gcc_assert (loop->order[n] == n);
4346 if (depends[n])
4347 loop->order[dim++] = n;
4349 for (n = 0; n < loop->dimen; n++)
4351 if (! depends[n])
4352 loop->order[dim++] = n;
4355 gcc_assert (dim == loop->dimen);
4356 break;
4358 #endif
4362 temporary:
4364 if (nDepend == 1)
4366 tree base_type = gfc_typenode_for_spec (&dest_expr->ts);
4367 if (GFC_ARRAY_TYPE_P (base_type)
4368 || GFC_DESCRIPTOR_TYPE_P (base_type))
4369 base_type = gfc_get_element_type (base_type);
4370 loop->temp_ss = gfc_get_temp_ss (base_type, dest->info->string_length,
4371 loop->dimen);
4372 gfc_add_ss_to_loop (loop, loop->temp_ss);
4374 else
4375 loop->temp_ss = NULL;
4379 /* Browse through each array's information from the scalarizer and set the loop
4380 bounds according to the "best" one (per dimension), i.e. the one which
4381 provides the most information (constant bounds, shape, etc.). */
4383 static void
4384 set_loop_bounds (gfc_loopinfo *loop)
4386 int n, dim, spec_dim;
4387 gfc_array_info *info;
4388 gfc_array_info *specinfo;
4389 gfc_ss *ss;
4390 tree tmp;
4391 gfc_ss **loopspec;
4392 bool dynamic[GFC_MAX_DIMENSIONS];
4393 mpz_t *cshape;
4394 mpz_t i;
4395 bool nonoptional_arr;
4397 loopspec = loop->specloop;
4399 mpz_init (i);
4400 for (n = 0; n < loop->dimen; n++)
4402 loopspec[n] = NULL;
4403 dynamic[n] = false;
4405 /* If there are both optional and nonoptional array arguments, scalarize
4406 over the nonoptional; otherwise, it does not matter as then all
4407 (optional) arrays have to be present per F2008, 125.2.12p3(6). */
4409 nonoptional_arr = false;
4411 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4412 if (ss->info->type != GFC_SS_SCALAR && ss->info->type != GFC_SS_TEMP
4413 && ss->info->type != GFC_SS_REFERENCE && !ss->info->can_be_null_ref)
4414 nonoptional_arr = true;
4416 /* We use one SS term, and use that to determine the bounds of the
4417 loop for this dimension. We try to pick the simplest term. */
4418 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4420 gfc_ss_type ss_type;
4422 ss_type = ss->info->type;
4423 if (ss_type == GFC_SS_SCALAR
4424 || ss_type == GFC_SS_TEMP
4425 || ss_type == GFC_SS_REFERENCE
4426 || (ss->info->can_be_null_ref && nonoptional_arr))
4427 continue;
4429 info = &ss->info->data.array;
4430 dim = ss->dim[n];
4432 if (loopspec[n] != NULL)
4434 specinfo = &loopspec[n]->info->data.array;
4435 spec_dim = loopspec[n]->dim[n];
4437 else
4439 /* Silence uninitialized warnings. */
4440 specinfo = NULL;
4441 spec_dim = 0;
4444 if (info->shape)
4446 gcc_assert (info->shape[dim]);
4447 /* The frontend has worked out the size for us. */
4448 if (!loopspec[n]
4449 || !specinfo->shape
4450 || !integer_zerop (specinfo->start[spec_dim]))
4451 /* Prefer zero-based descriptors if possible. */
4452 loopspec[n] = ss;
4453 continue;
4456 if (ss_type == GFC_SS_CONSTRUCTOR)
4458 gfc_constructor_base base;
4459 /* An unknown size constructor will always be rank one.
4460 Higher rank constructors will either have known shape,
4461 or still be wrapped in a call to reshape. */
4462 gcc_assert (loop->dimen == 1);
4464 /* Always prefer to use the constructor bounds if the size
4465 can be determined at compile time. Prefer not to otherwise,
4466 since the general case involves realloc, and it's better to
4467 avoid that overhead if possible. */
4468 base = ss->info->expr->value.constructor;
4469 dynamic[n] = gfc_get_array_constructor_size (&i, base);
4470 if (!dynamic[n] || !loopspec[n])
4471 loopspec[n] = ss;
4472 continue;
4475 /* Avoid using an allocatable lhs in an assignment, since
4476 there might be a reallocation coming. */
4477 if (loopspec[n] && ss->is_alloc_lhs)
4478 continue;
4480 if (!loopspec[n])
4481 loopspec[n] = ss;
4482 /* Criteria for choosing a loop specifier (most important first):
4483 doesn't need realloc
4484 stride of one
4485 known stride
4486 known lower bound
4487 known upper bound
4489 else if (loopspec[n]->info->type == GFC_SS_CONSTRUCTOR && dynamic[n])
4490 loopspec[n] = ss;
4491 else if (integer_onep (info->stride[dim])
4492 && !integer_onep (specinfo->stride[spec_dim]))
4493 loopspec[n] = ss;
4494 else if (INTEGER_CST_P (info->stride[dim])
4495 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
4496 loopspec[n] = ss;
4497 else if (INTEGER_CST_P (info->start[dim])
4498 && !INTEGER_CST_P (specinfo->start[spec_dim])
4499 && integer_onep (info->stride[dim])
4500 == integer_onep (specinfo->stride[spec_dim])
4501 && INTEGER_CST_P (info->stride[dim])
4502 == INTEGER_CST_P (specinfo->stride[spec_dim]))
4503 loopspec[n] = ss;
4504 /* We don't work out the upper bound.
4505 else if (INTEGER_CST_P (info->finish[n])
4506 && ! INTEGER_CST_P (specinfo->finish[n]))
4507 loopspec[n] = ss; */
4510 /* We should have found the scalarization loop specifier. If not,
4511 that's bad news. */
4512 gcc_assert (loopspec[n]);
4514 info = &loopspec[n]->info->data.array;
4515 dim = loopspec[n]->dim[n];
4517 /* Set the extents of this range. */
4518 cshape = info->shape;
4519 if (cshape && INTEGER_CST_P (info->start[dim])
4520 && INTEGER_CST_P (info->stride[dim]))
4522 loop->from[n] = info->start[dim];
4523 mpz_set (i, cshape[get_array_ref_dim_for_loop_dim (loopspec[n], n)]);
4524 mpz_sub_ui (i, i, 1);
4525 /* To = from + (size - 1) * stride. */
4526 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
4527 if (!integer_onep (info->stride[dim]))
4528 tmp = fold_build2_loc (input_location, MULT_EXPR,
4529 gfc_array_index_type, tmp,
4530 info->stride[dim]);
4531 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
4532 gfc_array_index_type,
4533 loop->from[n], tmp);
4535 else
4537 loop->from[n] = info->start[dim];
4538 switch (loopspec[n]->info->type)
4540 case GFC_SS_CONSTRUCTOR:
4541 /* The upper bound is calculated when we expand the
4542 constructor. */
4543 gcc_assert (loop->to[n] == NULL_TREE);
4544 break;
4546 case GFC_SS_SECTION:
4547 /* Use the end expression if it exists and is not constant,
4548 so that it is only evaluated once. */
4549 loop->to[n] = info->end[dim];
4550 break;
4552 case GFC_SS_FUNCTION:
4553 /* The loop bound will be set when we generate the call. */
4554 gcc_assert (loop->to[n] == NULL_TREE);
4555 break;
4557 case GFC_SS_INTRINSIC:
4559 gfc_expr *expr = loopspec[n]->info->expr;
4561 /* The {l,u}bound of an assumed rank. */
4562 gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND
4563 || expr->value.function.isym->id == GFC_ISYM_UBOUND)
4564 && expr->value.function.actual->next->expr == NULL
4565 && expr->value.function.actual->expr->rank == -1);
4567 loop->to[n] = info->end[dim];
4568 break;
4571 default:
4572 gcc_unreachable ();
4576 /* Transform everything so we have a simple incrementing variable. */
4577 if (integer_onep (info->stride[dim]))
4578 info->delta[dim] = gfc_index_zero_node;
4579 else
4581 /* Set the delta for this section. */
4582 info->delta[dim] = gfc_evaluate_now (loop->from[n], &loop->pre);
4583 /* Number of iterations is (end - start + step) / step.
4584 with start = 0, this simplifies to
4585 last = end / step;
4586 for (i = 0; i<=last; i++){...}; */
4587 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4588 gfc_array_index_type, loop->to[n],
4589 loop->from[n]);
4590 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
4591 gfc_array_index_type, tmp, info->stride[dim]);
4592 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
4593 tmp, build_int_cst (gfc_array_index_type, -1));
4594 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
4595 /* Make the loop variable start at 0. */
4596 loop->from[n] = gfc_index_zero_node;
4599 mpz_clear (i);
4601 for (loop = loop->nested; loop; loop = loop->next)
4602 set_loop_bounds (loop);
4606 /* Initialize the scalarization loop. Creates the loop variables. Determines
4607 the range of the loop variables. Creates a temporary if required.
4608 Also generates code for scalar expressions which have been
4609 moved outside the loop. */
4611 void
4612 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
4614 gfc_ss *tmp_ss;
4615 tree tmp;
4617 set_loop_bounds (loop);
4619 /* Add all the scalar code that can be taken out of the loops.
4620 This may include calculating the loop bounds, so do it before
4621 allocating the temporary. */
4622 gfc_add_loop_ss_code (loop, loop->ss, false, where);
4624 tmp_ss = loop->temp_ss;
4625 /* If we want a temporary then create it. */
4626 if (tmp_ss != NULL)
4628 gfc_ss_info *tmp_ss_info;
4630 tmp_ss_info = tmp_ss->info;
4631 gcc_assert (tmp_ss_info->type == GFC_SS_TEMP);
4632 gcc_assert (loop->parent == NULL);
4634 /* Make absolutely sure that this is a complete type. */
4635 if (tmp_ss_info->string_length)
4636 tmp_ss_info->data.temp.type
4637 = gfc_get_character_type_len_for_eltype
4638 (TREE_TYPE (tmp_ss_info->data.temp.type),
4639 tmp_ss_info->string_length);
4641 tmp = tmp_ss_info->data.temp.type;
4642 memset (&tmp_ss_info->data.array, 0, sizeof (gfc_array_info));
4643 tmp_ss_info->type = GFC_SS_SECTION;
4645 gcc_assert (tmp_ss->dimen != 0);
4647 gfc_trans_create_temp_array (&loop->pre, &loop->post, tmp_ss, tmp,
4648 NULL_TREE, false, true, false, where);
4651 /* For array parameters we don't have loop variables, so don't calculate the
4652 translations. */
4653 if (!loop->array_parameter)
4654 gfc_set_delta (loop);
4658 /* Calculates how to transform from loop variables to array indices for each
4659 array: once loop bounds are chosen, sets the difference (DELTA field) between
4660 loop bounds and array reference bounds, for each array info. */
4662 void
4663 gfc_set_delta (gfc_loopinfo *loop)
4665 gfc_ss *ss, **loopspec;
4666 gfc_array_info *info;
4667 tree tmp;
4668 int n, dim;
4670 loopspec = loop->specloop;
4672 /* Calculate the translation from loop variables to array indices. */
4673 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
4675 gfc_ss_type ss_type;
4677 ss_type = ss->info->type;
4678 if (ss_type != GFC_SS_SECTION
4679 && ss_type != GFC_SS_COMPONENT
4680 && ss_type != GFC_SS_CONSTRUCTOR)
4681 continue;
4683 info = &ss->info->data.array;
4685 for (n = 0; n < ss->dimen; n++)
4687 /* If we are specifying the range the delta is already set. */
4688 if (loopspec[n] != ss)
4690 dim = ss->dim[n];
4692 /* Calculate the offset relative to the loop variable.
4693 First multiply by the stride. */
4694 tmp = loop->from[n];
4695 if (!integer_onep (info->stride[dim]))
4696 tmp = fold_build2_loc (input_location, MULT_EXPR,
4697 gfc_array_index_type,
4698 tmp, info->stride[dim]);
4700 /* Then subtract this from our starting value. */
4701 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4702 gfc_array_index_type,
4703 info->start[dim], tmp);
4705 info->delta[dim] = gfc_evaluate_now (tmp, &loop->pre);
4710 for (loop = loop->nested; loop; loop = loop->next)
4711 gfc_set_delta (loop);
4715 /* Calculate the size of a given array dimension from the bounds. This
4716 is simply (ubound - lbound + 1) if this expression is positive
4717 or 0 if it is negative (pick either one if it is zero). Optionally
4718 (if or_expr is present) OR the (expression != 0) condition to it. */
4720 tree
4721 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
4723 tree res;
4724 tree cond;
4726 /* Calculate (ubound - lbound + 1). */
4727 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4728 ubound, lbound);
4729 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
4730 gfc_index_one_node);
4732 /* Check whether the size for this dimension is negative. */
4733 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, res,
4734 gfc_index_zero_node);
4735 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
4736 gfc_index_zero_node, res);
4738 /* Build OR expression. */
4739 if (or_expr)
4740 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
4741 boolean_type_node, *or_expr, cond);
4743 return res;
4747 /* For an array descriptor, get the total number of elements. This is just
4748 the product of the extents along from_dim to to_dim. */
4750 static tree
4751 gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
4753 tree res;
4754 int dim;
4756 res = gfc_index_one_node;
4758 for (dim = from_dim; dim < to_dim; ++dim)
4760 tree lbound;
4761 tree ubound;
4762 tree extent;
4764 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
4765 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
4767 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
4768 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4769 res, extent);
4772 return res;
4776 /* Full size of an array. */
4778 tree
4779 gfc_conv_descriptor_size (tree desc, int rank)
4781 return gfc_conv_descriptor_size_1 (desc, 0, rank);
4785 /* Size of a coarray for all dimensions but the last. */
4787 tree
4788 gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
4790 return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
4794 /* Fills in an array descriptor, and returns the size of the array.
4795 The size will be a simple_val, ie a variable or a constant. Also
4796 calculates the offset of the base. The pointer argument overflow,
4797 which should be of integer type, will increase in value if overflow
4798 occurs during the size calculation. Returns the size of the array.
4800 stride = 1;
4801 offset = 0;
4802 for (n = 0; n < rank; n++)
4804 a.lbound[n] = specified_lower_bound;
4805 offset = offset + a.lbond[n] * stride;
4806 size = 1 - lbound;
4807 a.ubound[n] = specified_upper_bound;
4808 a.stride[n] = stride;
4809 size = size >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
4810 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
4811 stride = stride * size;
4813 for (n = rank; n < rank+corank; n++)
4814 (Set lcobound/ucobound as above.)
4815 element_size = sizeof (array element);
4816 if (!rank)
4817 return element_size
4818 stride = (size_t) stride;
4819 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
4820 stride = stride * element_size;
4821 return (stride);
4822 } */
4823 /*GCC ARRAYS*/
4825 static tree
4826 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
4827 gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
4828 stmtblock_t * descriptor_block, tree * overflow,
4829 tree expr3_elem_size, tree *nelems, gfc_expr *expr3)
4831 tree type;
4832 tree tmp;
4833 tree size;
4834 tree offset;
4835 tree stride;
4836 tree element_size;
4837 tree or_expr;
4838 tree thencase;
4839 tree elsecase;
4840 tree cond;
4841 tree var;
4842 stmtblock_t thenblock;
4843 stmtblock_t elseblock;
4844 gfc_expr *ubound;
4845 gfc_se se;
4846 int n;
4848 type = TREE_TYPE (descriptor);
4850 stride = gfc_index_one_node;
4851 offset = gfc_index_zero_node;
4853 /* Set the dtype. */
4854 tmp = gfc_conv_descriptor_dtype (descriptor);
4855 gfc_add_modify (descriptor_block, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
4857 or_expr = boolean_false_node;
4859 for (n = 0; n < rank; n++)
4861 tree conv_lbound;
4862 tree conv_ubound;
4864 /* We have 3 possibilities for determining the size of the array:
4865 lower == NULL => lbound = 1, ubound = upper[n]
4866 upper[n] = NULL => lbound = 1, ubound = lower[n]
4867 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
4868 ubound = upper[n];
4870 /* Set lower bound. */
4871 gfc_init_se (&se, NULL);
4872 if (lower == NULL)
4873 se.expr = gfc_index_one_node;
4874 else
4876 gcc_assert (lower[n]);
4877 if (ubound)
4879 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
4880 gfc_add_block_to_block (pblock, &se.pre);
4882 else
4884 se.expr = gfc_index_one_node;
4885 ubound = lower[n];
4888 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
4889 gfc_rank_cst[n], se.expr);
4890 conv_lbound = se.expr;
4892 /* Work out the offset for this component. */
4893 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4894 se.expr, stride);
4895 offset = fold_build2_loc (input_location, MINUS_EXPR,
4896 gfc_array_index_type, offset, tmp);
4898 /* Set upper bound. */
4899 gfc_init_se (&se, NULL);
4900 gcc_assert (ubound);
4901 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
4902 gfc_add_block_to_block (pblock, &se.pre);
4904 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
4905 gfc_rank_cst[n], se.expr);
4906 conv_ubound = se.expr;
4908 /* Store the stride. */
4909 gfc_conv_descriptor_stride_set (descriptor_block, descriptor,
4910 gfc_rank_cst[n], stride);
4912 /* Calculate size and check whether extent is negative. */
4913 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
4914 size = gfc_evaluate_now (size, pblock);
4916 /* Check whether multiplying the stride by the number of
4917 elements in this dimension would overflow. We must also check
4918 whether the current dimension has zero size in order to avoid
4919 division by zero.
4921 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
4922 gfc_array_index_type,
4923 fold_convert (gfc_array_index_type,
4924 TYPE_MAX_VALUE (gfc_array_index_type)),
4925 size);
4926 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
4927 boolean_type_node, tmp, stride));
4928 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4929 integer_one_node, integer_zero_node);
4930 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
4931 boolean_type_node, size,
4932 gfc_index_zero_node));
4933 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4934 integer_zero_node, tmp);
4935 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
4936 *overflow, tmp);
4937 *overflow = gfc_evaluate_now (tmp, pblock);
4939 /* Multiply the stride by the number of elements in this dimension. */
4940 stride = fold_build2_loc (input_location, MULT_EXPR,
4941 gfc_array_index_type, stride, size);
4942 stride = gfc_evaluate_now (stride, pblock);
4945 for (n = rank; n < rank + corank; n++)
4947 ubound = upper[n];
4949 /* Set lower bound. */
4950 gfc_init_se (&se, NULL);
4951 if (lower == NULL || lower[n] == NULL)
4953 gcc_assert (n == rank + corank - 1);
4954 se.expr = gfc_index_one_node;
4956 else
4958 if (ubound || n == rank + corank - 1)
4960 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
4961 gfc_add_block_to_block (pblock, &se.pre);
4963 else
4965 se.expr = gfc_index_one_node;
4966 ubound = lower[n];
4969 gfc_conv_descriptor_lbound_set (descriptor_block, descriptor,
4970 gfc_rank_cst[n], se.expr);
4972 if (n < rank + corank - 1)
4974 gfc_init_se (&se, NULL);
4975 gcc_assert (ubound);
4976 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
4977 gfc_add_block_to_block (pblock, &se.pre);
4978 gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
4979 gfc_rank_cst[n], se.expr);
4983 /* The stride is the number of elements in the array, so multiply by the
4984 size of an element to get the total size. Obviously, if there is a
4985 SOURCE expression (expr3) we must use its element size. */
4986 if (expr3_elem_size != NULL_TREE)
4987 tmp = expr3_elem_size;
4988 else if (expr3 != NULL)
4990 if (expr3->ts.type == BT_CLASS)
4992 gfc_se se_sz;
4993 gfc_expr *sz = gfc_copy_expr (expr3);
4994 gfc_add_vptr_component (sz);
4995 gfc_add_size_component (sz);
4996 gfc_init_se (&se_sz, NULL);
4997 gfc_conv_expr (&se_sz, sz);
4998 gfc_free_expr (sz);
4999 tmp = se_sz.expr;
5001 else
5003 tmp = gfc_typenode_for_spec (&expr3->ts);
5004 tmp = TYPE_SIZE_UNIT (tmp);
5007 else
5008 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5010 /* Convert to size_t. */
5011 element_size = fold_convert (size_type_node, tmp);
5013 if (rank == 0)
5014 return element_size;
5016 *nelems = gfc_evaluate_now (stride, pblock);
5017 stride = fold_convert (size_type_node, stride);
5019 /* First check for overflow. Since an array of type character can
5020 have zero element_size, we must check for that before
5021 dividing. */
5022 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
5023 size_type_node,
5024 TYPE_MAX_VALUE (size_type_node), element_size);
5025 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
5026 boolean_type_node, tmp, stride));
5027 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5028 integer_one_node, integer_zero_node);
5029 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
5030 boolean_type_node, element_size,
5031 build_int_cst (size_type_node, 0)));
5032 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
5033 integer_zero_node, tmp);
5034 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
5035 *overflow, tmp);
5036 *overflow = gfc_evaluate_now (tmp, pblock);
5038 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
5039 stride, element_size);
5041 if (poffset != NULL)
5043 offset = gfc_evaluate_now (offset, pblock);
5044 *poffset = offset;
5047 if (integer_zerop (or_expr))
5048 return size;
5049 if (integer_onep (or_expr))
5050 return build_int_cst (size_type_node, 0);
5052 var = gfc_create_var (TREE_TYPE (size), "size");
5053 gfc_start_block (&thenblock);
5054 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
5055 thencase = gfc_finish_block (&thenblock);
5057 gfc_start_block (&elseblock);
5058 gfc_add_modify (&elseblock, var, size);
5059 elsecase = gfc_finish_block (&elseblock);
5061 tmp = gfc_evaluate_now (or_expr, pblock);
5062 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
5063 gfc_add_expr_to_block (pblock, tmp);
5065 return var;
5069 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
5070 the work for an ALLOCATE statement. */
5071 /*GCC ARRAYS*/
5073 bool
5074 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
5075 tree errlen, tree label_finish, tree expr3_elem_size,
5076 tree *nelems, gfc_expr *expr3)
5078 tree tmp;
5079 tree pointer;
5080 tree offset = NULL_TREE;
5081 tree token = NULL_TREE;
5082 tree size;
5083 tree msg;
5084 tree error = NULL_TREE;
5085 tree overflow; /* Boolean storing whether size calculation overflows. */
5086 tree var_overflow = NULL_TREE;
5087 tree cond;
5088 tree set_descriptor;
5089 stmtblock_t set_descriptor_block;
5090 stmtblock_t elseblock;
5091 gfc_expr **lower;
5092 gfc_expr **upper;
5093 gfc_ref *ref, *prev_ref = NULL;
5094 bool allocatable, coarray, dimension;
5096 ref = expr->ref;
5098 /* Find the last reference in the chain. */
5099 while (ref && ref->next != NULL)
5101 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
5102 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
5103 prev_ref = ref;
5104 ref = ref->next;
5107 if (ref == NULL || ref->type != REF_ARRAY)
5108 return false;
5110 if (!prev_ref)
5112 allocatable = expr->symtree->n.sym->attr.allocatable;
5113 coarray = expr->symtree->n.sym->attr.codimension;
5114 dimension = expr->symtree->n.sym->attr.dimension;
5116 else
5118 allocatable = prev_ref->u.c.component->attr.allocatable;
5119 coarray = prev_ref->u.c.component->attr.codimension;
5120 dimension = prev_ref->u.c.component->attr.dimension;
5123 if (!dimension)
5124 gcc_assert (coarray);
5126 /* Figure out the size of the array. */
5127 switch (ref->u.ar.type)
5129 case AR_ELEMENT:
5130 if (!coarray)
5132 lower = NULL;
5133 upper = ref->u.ar.start;
5134 break;
5136 /* Fall through. */
5138 case AR_SECTION:
5139 lower = ref->u.ar.start;
5140 upper = ref->u.ar.end;
5141 break;
5143 case AR_FULL:
5144 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
5146 lower = ref->u.ar.as->lower;
5147 upper = ref->u.ar.as->upper;
5148 break;
5150 default:
5151 gcc_unreachable ();
5152 break;
5155 overflow = integer_zero_node;
5157 gfc_init_block (&set_descriptor_block);
5158 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
5159 ref->u.ar.as->corank, &offset, lower, upper,
5160 &se->pre, &set_descriptor_block, &overflow,
5161 expr3_elem_size, nelems, expr3);
5163 if (dimension)
5166 var_overflow = gfc_create_var (integer_type_node, "overflow");
5167 gfc_add_modify (&se->pre, var_overflow, overflow);
5169 /* Generate the block of code handling overflow. */
5170 msg = gfc_build_addr_expr (pchar_type_node,
5171 gfc_build_localized_cstring_const
5172 ("Integer overflow when calculating the amount of "
5173 "memory to allocate"));
5174 error = build_call_expr_loc (input_location, gfor_fndecl_runtime_error,
5175 1, msg);
5178 if (status != NULL_TREE)
5180 tree status_type = TREE_TYPE (status);
5181 stmtblock_t set_status_block;
5183 gfc_start_block (&set_status_block);
5184 gfc_add_modify (&set_status_block, status,
5185 build_int_cst (status_type, LIBERROR_ALLOCATION));
5186 error = gfc_finish_block (&set_status_block);
5189 gfc_start_block (&elseblock);
5191 /* Allocate memory to store the data. */
5192 if (POINTER_TYPE_P (TREE_TYPE (se->expr)))
5193 se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
5195 pointer = gfc_conv_descriptor_data_get (se->expr);
5196 STRIP_NOPS (pointer);
5198 if (coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
5199 token = gfc_build_addr_expr (NULL_TREE,
5200 gfc_conv_descriptor_token (se->expr));
5202 /* The allocatable variant takes the old pointer as first argument. */
5203 if (allocatable)
5204 gfc_allocate_allocatable (&elseblock, pointer, size, token,
5205 status, errmsg, errlen, label_finish, expr);
5206 else
5207 gfc_allocate_using_malloc (&elseblock, pointer, size, status);
5209 if (dimension)
5211 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
5212 boolean_type_node, var_overflow, integer_zero_node));
5213 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
5214 error, gfc_finish_block (&elseblock));
5216 else
5217 tmp = gfc_finish_block (&elseblock);
5219 gfc_add_expr_to_block (&se->pre, tmp);
5221 if (expr->ts.type == BT_CLASS)
5223 tmp = build_int_cst (unsigned_char_type_node, 0);
5224 /* With class objects, it is best to play safe and null the
5225 memory because we cannot know if dynamic types have allocatable
5226 components or not. */
5227 tmp = build_call_expr_loc (input_location,
5228 builtin_decl_explicit (BUILT_IN_MEMSET),
5229 3, pointer, tmp, size);
5230 gfc_add_expr_to_block (&se->pre, tmp);
5233 /* Update the array descriptors. */
5234 if (dimension)
5235 gfc_conv_descriptor_offset_set (&set_descriptor_block, se->expr, offset);
5237 set_descriptor = gfc_finish_block (&set_descriptor_block);
5238 if (status != NULL_TREE)
5240 cond = fold_build2_loc (input_location, EQ_EXPR,
5241 boolean_type_node, status,
5242 build_int_cst (TREE_TYPE (status), 0));
5243 gfc_add_expr_to_block (&se->pre,
5244 fold_build3_loc (input_location, COND_EXPR, void_type_node,
5245 gfc_likely (cond), set_descriptor,
5246 build_empty_stmt (input_location)));
5248 else
5249 gfc_add_expr_to_block (&se->pre, set_descriptor);
5251 if ((expr->ts.type == BT_DERIVED)
5252 && expr->ts.u.derived->attr.alloc_comp)
5254 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, se->expr,
5255 ref->u.ar.as->rank);
5256 gfc_add_expr_to_block (&se->pre, tmp);
5259 return true;
5263 /* Deallocate an array variable. Also used when an allocated variable goes
5264 out of scope. */
5265 /*GCC ARRAYS*/
5267 tree
5268 gfc_array_deallocate (tree descriptor, tree pstat, tree errmsg, tree errlen,
5269 tree label_finish, gfc_expr* expr)
5271 tree var;
5272 tree tmp;
5273 stmtblock_t block;
5274 bool coarray = gfc_is_coarray (expr);
5276 gfc_start_block (&block);
5278 /* Get a pointer to the data. */
5279 var = gfc_conv_descriptor_data_get (descriptor);
5280 STRIP_NOPS (var);
5282 /* Parameter is the address of the data component. */
5283 tmp = gfc_deallocate_with_status (coarray ? descriptor : var, pstat, errmsg,
5284 errlen, label_finish, false, expr, coarray);
5285 gfc_add_expr_to_block (&block, tmp);
5287 /* Zero the data pointer; only for coarrays an error can occur and then
5288 the allocation status may not be changed. */
5289 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5290 var, build_int_cst (TREE_TYPE (var), 0));
5291 if (pstat != NULL_TREE && coarray && gfc_option.coarray == GFC_FCOARRAY_LIB)
5293 tree cond;
5294 tree stat = build_fold_indirect_ref_loc (input_location, pstat);
5296 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5297 stat, build_int_cst (TREE_TYPE (stat), 0));
5298 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5299 cond, tmp, build_empty_stmt (input_location));
5302 gfc_add_expr_to_block (&block, tmp);
5304 return gfc_finish_block (&block);
5308 /* Create an array constructor from an initialization expression.
5309 We assume the frontend already did any expansions and conversions. */
5311 tree
5312 gfc_conv_array_initializer (tree type, gfc_expr * expr)
5314 gfc_constructor *c;
5315 tree tmp;
5316 gfc_se se;
5317 HOST_WIDE_INT hi;
5318 unsigned HOST_WIDE_INT lo;
5319 tree index, range;
5320 vec<constructor_elt, va_gc> *v = NULL;
5322 if (expr->expr_type == EXPR_VARIABLE
5323 && expr->symtree->n.sym->attr.flavor == FL_PARAMETER
5324 && expr->symtree->n.sym->value)
5325 expr = expr->symtree->n.sym->value;
5327 switch (expr->expr_type)
5329 case EXPR_CONSTANT:
5330 case EXPR_STRUCTURE:
5331 /* A single scalar or derived type value. Create an array with all
5332 elements equal to that value. */
5333 gfc_init_se (&se, NULL);
5335 if (expr->expr_type == EXPR_CONSTANT)
5336 gfc_conv_constant (&se, expr);
5337 else
5338 gfc_conv_structure (&se, expr, 1);
5340 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5341 gcc_assert (tmp && INTEGER_CST_P (tmp));
5342 hi = TREE_INT_CST_HIGH (tmp);
5343 lo = TREE_INT_CST_LOW (tmp);
5344 lo++;
5345 if (lo == 0)
5346 hi++;
5347 /* This will probably eat buckets of memory for large arrays. */
5348 while (hi != 0 || lo != 0)
5350 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
5351 if (lo == 0)
5352 hi--;
5353 lo--;
5355 break;
5357 case EXPR_ARRAY:
5358 /* Create a vector of all the elements. */
5359 for (c = gfc_constructor_first (expr->value.constructor);
5360 c; c = gfc_constructor_next (c))
5362 if (c->iterator)
5364 /* Problems occur when we get something like
5365 integer :: a(lots) = (/(i, i=1, lots)/) */
5366 gfc_fatal_error ("The number of elements in the array constructor "
5367 "at %L requires an increase of the allowed %d "
5368 "upper limit. See -fmax-array-constructor "
5369 "option", &expr->where,
5370 gfc_option.flag_max_array_constructor);
5371 return NULL_TREE;
5373 if (mpz_cmp_si (c->offset, 0) != 0)
5374 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5375 else
5376 index = NULL_TREE;
5378 if (mpz_cmp_si (c->repeat, 1) > 0)
5380 tree tmp1, tmp2;
5381 mpz_t maxval;
5383 mpz_init (maxval);
5384 mpz_add (maxval, c->offset, c->repeat);
5385 mpz_sub_ui (maxval, maxval, 1);
5386 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5387 if (mpz_cmp_si (c->offset, 0) != 0)
5389 mpz_add_ui (maxval, c->offset, 1);
5390 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
5392 else
5393 tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
5395 range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
5396 mpz_clear (maxval);
5398 else
5399 range = NULL;
5401 gfc_init_se (&se, NULL);
5402 switch (c->expr->expr_type)
5404 case EXPR_CONSTANT:
5405 gfc_conv_constant (&se, c->expr);
5406 break;
5408 case EXPR_STRUCTURE:
5409 gfc_conv_structure (&se, c->expr, 1);
5410 break;
5412 default:
5413 /* Catch those occasional beasts that do not simplify
5414 for one reason or another, assuming that if they are
5415 standard defying the frontend will catch them. */
5416 gfc_conv_expr (&se, c->expr);
5417 break;
5420 if (range == NULL_TREE)
5421 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5422 else
5424 if (index != NULL_TREE)
5425 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
5426 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
5429 break;
5431 case EXPR_NULL:
5432 return gfc_build_null_descriptor (type);
5434 default:
5435 gcc_unreachable ();
5438 /* Create a constructor from the list of elements. */
5439 tmp = build_constructor (type, v);
5440 TREE_CONSTANT (tmp) = 1;
5441 return tmp;
5445 /* Generate code to evaluate non-constant coarray cobounds. */
5447 void
5448 gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
5449 const gfc_symbol *sym)
5451 int dim;
5452 tree ubound;
5453 tree lbound;
5454 gfc_se se;
5455 gfc_array_spec *as;
5457 as = sym->as;
5459 for (dim = as->rank; dim < as->rank + as->corank; dim++)
5461 /* Evaluate non-constant array bound expressions. */
5462 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
5463 if (as->lower[dim] && !INTEGER_CST_P (lbound))
5465 gfc_init_se (&se, NULL);
5466 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
5467 gfc_add_block_to_block (pblock, &se.pre);
5468 gfc_add_modify (pblock, lbound, se.expr);
5470 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
5471 if (as->upper[dim] && !INTEGER_CST_P (ubound))
5473 gfc_init_se (&se, NULL);
5474 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
5475 gfc_add_block_to_block (pblock, &se.pre);
5476 gfc_add_modify (pblock, ubound, se.expr);
5482 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
5483 returns the size (in elements) of the array. */
5485 static tree
5486 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
5487 stmtblock_t * pblock)
5489 gfc_array_spec *as;
5490 tree size;
5491 tree stride;
5492 tree offset;
5493 tree ubound;
5494 tree lbound;
5495 tree tmp;
5496 gfc_se se;
5498 int dim;
5500 as = sym->as;
5502 size = gfc_index_one_node;
5503 offset = gfc_index_zero_node;
5504 for (dim = 0; dim < as->rank; dim++)
5506 /* Evaluate non-constant array bound expressions. */
5507 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
5508 if (as->lower[dim] && !INTEGER_CST_P (lbound))
5510 gfc_init_se (&se, NULL);
5511 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
5512 gfc_add_block_to_block (pblock, &se.pre);
5513 gfc_add_modify (pblock, lbound, se.expr);
5515 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
5516 if (as->upper[dim] && !INTEGER_CST_P (ubound))
5518 gfc_init_se (&se, NULL);
5519 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
5520 gfc_add_block_to_block (pblock, &se.pre);
5521 gfc_add_modify (pblock, ubound, se.expr);
5523 /* The offset of this dimension. offset = offset - lbound * stride. */
5524 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5525 lbound, size);
5526 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
5527 offset, tmp);
5529 /* The size of this dimension, and the stride of the next. */
5530 if (dim + 1 < as->rank)
5531 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
5532 else
5533 stride = GFC_TYPE_ARRAY_SIZE (type);
5535 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
5537 /* Calculate stride = size * (ubound + 1 - lbound). */
5538 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5539 gfc_array_index_type,
5540 gfc_index_one_node, lbound);
5541 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5542 gfc_array_index_type, ubound, tmp);
5543 tmp = fold_build2_loc (input_location, MULT_EXPR,
5544 gfc_array_index_type, size, tmp);
5545 if (stride)
5546 gfc_add_modify (pblock, stride, tmp);
5547 else
5548 stride = gfc_evaluate_now (tmp, pblock);
5550 /* Make sure that negative size arrays are translated
5551 to being zero size. */
5552 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
5553 stride, gfc_index_zero_node);
5554 tmp = fold_build3_loc (input_location, COND_EXPR,
5555 gfc_array_index_type, tmp,
5556 stride, gfc_index_zero_node);
5557 gfc_add_modify (pblock, stride, tmp);
5560 size = stride;
5563 gfc_trans_array_cobounds (type, pblock, sym);
5564 gfc_trans_vla_type_sizes (sym, pblock);
5566 *poffset = offset;
5567 return size;
5571 /* Generate code to initialize/allocate an array variable. */
5573 void
5574 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
5575 gfc_wrapped_block * block)
5577 stmtblock_t init;
5578 tree type;
5579 tree tmp = NULL_TREE;
5580 tree size;
5581 tree offset;
5582 tree space;
5583 tree inittree;
5584 bool onstack;
5586 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
5588 /* Do nothing for USEd variables. */
5589 if (sym->attr.use_assoc)
5590 return;
5592 type = TREE_TYPE (decl);
5593 gcc_assert (GFC_ARRAY_TYPE_P (type));
5594 onstack = TREE_CODE (type) != POINTER_TYPE;
5596 gfc_init_block (&init);
5598 /* Evaluate character string length. */
5599 if (sym->ts.type == BT_CHARACTER
5600 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
5602 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5604 gfc_trans_vla_type_sizes (sym, &init);
5606 /* Emit a DECL_EXPR for this variable, which will cause the
5607 gimplifier to allocate storage, and all that good stuff. */
5608 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
5609 gfc_add_expr_to_block (&init, tmp);
5612 if (onstack)
5614 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5615 return;
5618 type = TREE_TYPE (type);
5620 gcc_assert (!sym->attr.use_assoc);
5621 gcc_assert (!TREE_STATIC (decl));
5622 gcc_assert (!sym->module);
5624 if (sym->ts.type == BT_CHARACTER
5625 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
5626 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5628 size = gfc_trans_array_bounds (type, sym, &offset, &init);
5630 /* Don't actually allocate space for Cray Pointees. */
5631 if (sym->attr.cray_pointee)
5633 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5634 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5636 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5637 return;
5640 if (gfc_option.flag_stack_arrays)
5642 gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
5643 space = build_decl (sym->declared_at.lb->location,
5644 VAR_DECL, create_tmp_var_name ("A"),
5645 TREE_TYPE (TREE_TYPE (decl)));
5646 gfc_trans_vla_type_sizes (sym, &init);
5648 else
5650 /* The size is the number of elements in the array, so multiply by the
5651 size of an element to get the total size. */
5652 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
5653 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5654 size, fold_convert (gfc_array_index_type, tmp));
5656 /* Allocate memory to hold the data. */
5657 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
5658 gfc_add_modify (&init, decl, tmp);
5660 /* Free the temporary. */
5661 tmp = gfc_call_free (convert (pvoid_type_node, decl));
5662 space = NULL_TREE;
5665 /* Set offset of the array. */
5666 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5667 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5669 /* Automatic arrays should not have initializers. */
5670 gcc_assert (!sym->value);
5672 inittree = gfc_finish_block (&init);
5674 if (space)
5676 tree addr;
5677 pushdecl (space);
5679 /* Don't create new scope, emit the DECL_EXPR in exactly the scope
5680 where also space is located. */
5681 gfc_init_block (&init);
5682 tmp = fold_build1_loc (input_location, DECL_EXPR,
5683 TREE_TYPE (space), space);
5684 gfc_add_expr_to_block (&init, tmp);
5685 addr = fold_build1_loc (sym->declared_at.lb->location,
5686 ADDR_EXPR, TREE_TYPE (decl), space);
5687 gfc_add_modify (&init, decl, addr);
5688 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
5689 tmp = NULL_TREE;
5691 gfc_add_init_cleanup (block, inittree, tmp);
5695 /* Generate entry and exit code for g77 calling convention arrays. */
5697 void
5698 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
5700 tree parm;
5701 tree type;
5702 locus loc;
5703 tree offset;
5704 tree tmp;
5705 tree stmt;
5706 stmtblock_t init;
5708 gfc_save_backend_locus (&loc);
5709 gfc_set_backend_locus (&sym->declared_at);
5711 /* Descriptor type. */
5712 parm = sym->backend_decl;
5713 type = TREE_TYPE (parm);
5714 gcc_assert (GFC_ARRAY_TYPE_P (type));
5716 gfc_start_block (&init);
5718 if (sym->ts.type == BT_CHARACTER
5719 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
5720 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5722 /* Evaluate the bounds of the array. */
5723 gfc_trans_array_bounds (type, sym, &offset, &init);
5725 /* Set the offset. */
5726 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5727 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5729 /* Set the pointer itself if we aren't using the parameter directly. */
5730 if (TREE_CODE (parm) != PARM_DECL)
5732 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
5733 gfc_add_modify (&init, parm, tmp);
5735 stmt = gfc_finish_block (&init);
5737 gfc_restore_backend_locus (&loc);
5739 /* Add the initialization code to the start of the function. */
5741 if (sym->attr.optional || sym->attr.not_always_present)
5743 tmp = gfc_conv_expr_present (sym);
5744 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
5747 gfc_add_init_cleanup (block, stmt, NULL_TREE);
5751 /* Modify the descriptor of an array parameter so that it has the
5752 correct lower bound. Also move the upper bound accordingly.
5753 If the array is not packed, it will be copied into a temporary.
5754 For each dimension we set the new lower and upper bounds. Then we copy the
5755 stride and calculate the offset for this dimension. We also work out
5756 what the stride of a packed array would be, and see it the two match.
5757 If the array need repacking, we set the stride to the values we just
5758 calculated, recalculate the offset and copy the array data.
5759 Code is also added to copy the data back at the end of the function.
5762 void
5763 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
5764 gfc_wrapped_block * block)
5766 tree size;
5767 tree type;
5768 tree offset;
5769 locus loc;
5770 stmtblock_t init;
5771 tree stmtInit, stmtCleanup;
5772 tree lbound;
5773 tree ubound;
5774 tree dubound;
5775 tree dlbound;
5776 tree dumdesc;
5777 tree tmp;
5778 tree stride, stride2;
5779 tree stmt_packed;
5780 tree stmt_unpacked;
5781 tree partial;
5782 gfc_se se;
5783 int n;
5784 int checkparm;
5785 int no_repack;
5786 bool optional_arg;
5788 /* Do nothing for pointer and allocatable arrays. */
5789 if (sym->attr.pointer || sym->attr.allocatable)
5790 return;
5792 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
5794 gfc_trans_g77_array (sym, block);
5795 return;
5798 gfc_save_backend_locus (&loc);
5799 gfc_set_backend_locus (&sym->declared_at);
5801 /* Descriptor type. */
5802 type = TREE_TYPE (tmpdesc);
5803 gcc_assert (GFC_ARRAY_TYPE_P (type));
5804 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5805 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
5806 gfc_start_block (&init);
5808 if (sym->ts.type == BT_CHARACTER
5809 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
5810 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
5812 checkparm = (sym->as->type == AS_EXPLICIT
5813 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
5815 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
5816 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
5818 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
5820 /* For non-constant shape arrays we only check if the first dimension
5821 is contiguous. Repacking higher dimensions wouldn't gain us
5822 anything as we still don't know the array stride. */
5823 partial = gfc_create_var (boolean_type_node, "partial");
5824 TREE_USED (partial) = 1;
5825 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
5826 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, tmp,
5827 gfc_index_one_node);
5828 gfc_add_modify (&init, partial, tmp);
5830 else
5831 partial = NULL_TREE;
5833 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
5834 here, however I think it does the right thing. */
5835 if (no_repack)
5837 /* Set the first stride. */
5838 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
5839 stride = gfc_evaluate_now (stride, &init);
5841 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
5842 stride, gfc_index_zero_node);
5843 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
5844 tmp, gfc_index_one_node, stride);
5845 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
5846 gfc_add_modify (&init, stride, tmp);
5848 /* Allow the user to disable array repacking. */
5849 stmt_unpacked = NULL_TREE;
5851 else
5853 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
5854 /* A library call to repack the array if necessary. */
5855 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5856 stmt_unpacked = build_call_expr_loc (input_location,
5857 gfor_fndecl_in_pack, 1, tmp);
5859 stride = gfc_index_one_node;
5861 if (gfc_option.warn_array_temp)
5862 gfc_warning ("Creating array temporary at %L", &loc);
5865 /* This is for the case where the array data is used directly without
5866 calling the repack function. */
5867 if (no_repack || partial != NULL_TREE)
5868 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
5869 else
5870 stmt_packed = NULL_TREE;
5872 /* Assign the data pointer. */
5873 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
5875 /* Don't repack unknown shape arrays when the first stride is 1. */
5876 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
5877 partial, stmt_packed, stmt_unpacked);
5879 else
5880 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
5881 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
5883 offset = gfc_index_zero_node;
5884 size = gfc_index_one_node;
5886 /* Evaluate the bounds of the array. */
5887 for (n = 0; n < sym->as->rank; n++)
5889 if (checkparm || !sym->as->upper[n])
5891 /* Get the bounds of the actual parameter. */
5892 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
5893 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
5895 else
5897 dubound = NULL_TREE;
5898 dlbound = NULL_TREE;
5901 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
5902 if (!INTEGER_CST_P (lbound))
5904 gfc_init_se (&se, NULL);
5905 gfc_conv_expr_type (&se, sym->as->lower[n],
5906 gfc_array_index_type);
5907 gfc_add_block_to_block (&init, &se.pre);
5908 gfc_add_modify (&init, lbound, se.expr);
5911 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
5912 /* Set the desired upper bound. */
5913 if (sym->as->upper[n])
5915 /* We know what we want the upper bound to be. */
5916 if (!INTEGER_CST_P (ubound))
5918 gfc_init_se (&se, NULL);
5919 gfc_conv_expr_type (&se, sym->as->upper[n],
5920 gfc_array_index_type);
5921 gfc_add_block_to_block (&init, &se.pre);
5922 gfc_add_modify (&init, ubound, se.expr);
5925 /* Check the sizes match. */
5926 if (checkparm)
5928 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
5929 char * msg;
5930 tree temp;
5932 temp = fold_build2_loc (input_location, MINUS_EXPR,
5933 gfc_array_index_type, ubound, lbound);
5934 temp = fold_build2_loc (input_location, PLUS_EXPR,
5935 gfc_array_index_type,
5936 gfc_index_one_node, temp);
5937 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
5938 gfc_array_index_type, dubound,
5939 dlbound);
5940 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
5941 gfc_array_index_type,
5942 gfc_index_one_node, stride2);
5943 tmp = fold_build2_loc (input_location, NE_EXPR,
5944 gfc_array_index_type, temp, stride2);
5945 asprintf (&msg, "Dimension %d of array '%s' has extent "
5946 "%%ld instead of %%ld", n+1, sym->name);
5948 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
5949 fold_convert (long_integer_type_node, temp),
5950 fold_convert (long_integer_type_node, stride2));
5952 free (msg);
5955 else
5957 /* For assumed shape arrays move the upper bound by the same amount
5958 as the lower bound. */
5959 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5960 gfc_array_index_type, dubound, dlbound);
5961 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5962 gfc_array_index_type, tmp, lbound);
5963 gfc_add_modify (&init, ubound, tmp);
5965 /* The offset of this dimension. offset = offset - lbound * stride. */
5966 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5967 lbound, stride);
5968 offset = fold_build2_loc (input_location, MINUS_EXPR,
5969 gfc_array_index_type, offset, tmp);
5971 /* The size of this dimension, and the stride of the next. */
5972 if (n + 1 < sym->as->rank)
5974 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
5976 if (no_repack || partial != NULL_TREE)
5977 stmt_unpacked =
5978 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
5980 /* Figure out the stride if not a known constant. */
5981 if (!INTEGER_CST_P (stride))
5983 if (no_repack)
5984 stmt_packed = NULL_TREE;
5985 else
5987 /* Calculate stride = size * (ubound + 1 - lbound). */
5988 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5989 gfc_array_index_type,
5990 gfc_index_one_node, lbound);
5991 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5992 gfc_array_index_type, ubound, tmp);
5993 size = fold_build2_loc (input_location, MULT_EXPR,
5994 gfc_array_index_type, size, tmp);
5995 stmt_packed = size;
5998 /* Assign the stride. */
5999 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
6000 tmp = fold_build3_loc (input_location, COND_EXPR,
6001 gfc_array_index_type, partial,
6002 stmt_unpacked, stmt_packed);
6003 else
6004 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
6005 gfc_add_modify (&init, stride, tmp);
6008 else
6010 stride = GFC_TYPE_ARRAY_SIZE (type);
6012 if (stride && !INTEGER_CST_P (stride))
6014 /* Calculate size = stride * (ubound + 1 - lbound). */
6015 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6016 gfc_array_index_type,
6017 gfc_index_one_node, lbound);
6018 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6019 gfc_array_index_type,
6020 ubound, tmp);
6021 tmp = fold_build2_loc (input_location, MULT_EXPR,
6022 gfc_array_index_type,
6023 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
6024 gfc_add_modify (&init, stride, tmp);
6029 gfc_trans_array_cobounds (type, &init, sym);
6031 /* Set the offset. */
6032 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
6033 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
6035 gfc_trans_vla_type_sizes (sym, &init);
6037 stmtInit = gfc_finish_block (&init);
6039 /* Only do the entry/initialization code if the arg is present. */
6040 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
6041 optional_arg = (sym->attr.optional
6042 || (sym->ns->proc_name->attr.entry_master
6043 && sym->attr.dummy));
6044 if (optional_arg)
6046 tmp = gfc_conv_expr_present (sym);
6047 stmtInit = build3_v (COND_EXPR, tmp, stmtInit,
6048 build_empty_stmt (input_location));
6051 /* Cleanup code. */
6052 if (no_repack)
6053 stmtCleanup = NULL_TREE;
6054 else
6056 stmtblock_t cleanup;
6057 gfc_start_block (&cleanup);
6059 if (sym->attr.intent != INTENT_IN)
6061 /* Copy the data back. */
6062 tmp = build_call_expr_loc (input_location,
6063 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
6064 gfc_add_expr_to_block (&cleanup, tmp);
6067 /* Free the temporary. */
6068 tmp = gfc_call_free (tmpdesc);
6069 gfc_add_expr_to_block (&cleanup, tmp);
6071 stmtCleanup = gfc_finish_block (&cleanup);
6073 /* Only do the cleanup if the array was repacked. */
6074 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
6075 tmp = gfc_conv_descriptor_data_get (tmp);
6076 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6077 tmp, tmpdesc);
6078 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6079 build_empty_stmt (input_location));
6081 if (optional_arg)
6083 tmp = gfc_conv_expr_present (sym);
6084 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
6085 build_empty_stmt (input_location));
6089 /* We don't need to free any memory allocated by internal_pack as it will
6090 be freed at the end of the function by pop_context. */
6091 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
6093 gfc_restore_backend_locus (&loc);
6097 /* Calculate the overall offset, including subreferences. */
6098 static void
6099 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
6100 bool subref, gfc_expr *expr)
6102 tree tmp;
6103 tree field;
6104 tree stride;
6105 tree index;
6106 gfc_ref *ref;
6107 gfc_se start;
6108 int n;
6110 /* If offset is NULL and this is not a subreferenced array, there is
6111 nothing to do. */
6112 if (offset == NULL_TREE)
6114 if (subref)
6115 offset = gfc_index_zero_node;
6116 else
6117 return;
6120 tmp = build_array_ref (desc, offset, NULL);
6122 /* Offset the data pointer for pointer assignments from arrays with
6123 subreferences; e.g. my_integer => my_type(:)%integer_component. */
6124 if (subref)
6126 /* Go past the array reference. */
6127 for (ref = expr->ref; ref; ref = ref->next)
6128 if (ref->type == REF_ARRAY &&
6129 ref->u.ar.type != AR_ELEMENT)
6131 ref = ref->next;
6132 break;
6135 /* Calculate the offset for each subsequent subreference. */
6136 for (; ref; ref = ref->next)
6138 switch (ref->type)
6140 case REF_COMPONENT:
6141 field = ref->u.c.component->backend_decl;
6142 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
6143 tmp = fold_build3_loc (input_location, COMPONENT_REF,
6144 TREE_TYPE (field),
6145 tmp, field, NULL_TREE);
6146 break;
6148 case REF_SUBSTRING:
6149 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
6150 gfc_init_se (&start, NULL);
6151 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
6152 gfc_add_block_to_block (block, &start.pre);
6153 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
6154 break;
6156 case REF_ARRAY:
6157 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
6158 && ref->u.ar.type == AR_ELEMENT);
6160 /* TODO - Add bounds checking. */
6161 stride = gfc_index_one_node;
6162 index = gfc_index_zero_node;
6163 for (n = 0; n < ref->u.ar.dimen; n++)
6165 tree itmp;
6166 tree jtmp;
6168 /* Update the index. */
6169 gfc_init_se (&start, NULL);
6170 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
6171 itmp = gfc_evaluate_now (start.expr, block);
6172 gfc_init_se (&start, NULL);
6173 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
6174 jtmp = gfc_evaluate_now (start.expr, block);
6175 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6176 gfc_array_index_type, itmp, jtmp);
6177 itmp = fold_build2_loc (input_location, MULT_EXPR,
6178 gfc_array_index_type, itmp, stride);
6179 index = fold_build2_loc (input_location, PLUS_EXPR,
6180 gfc_array_index_type, itmp, index);
6181 index = gfc_evaluate_now (index, block);
6183 /* Update the stride. */
6184 gfc_init_se (&start, NULL);
6185 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
6186 itmp = fold_build2_loc (input_location, MINUS_EXPR,
6187 gfc_array_index_type, start.expr,
6188 jtmp);
6189 itmp = fold_build2_loc (input_location, PLUS_EXPR,
6190 gfc_array_index_type,
6191 gfc_index_one_node, itmp);
6192 stride = fold_build2_loc (input_location, MULT_EXPR,
6193 gfc_array_index_type, stride, itmp);
6194 stride = gfc_evaluate_now (stride, block);
6197 /* Apply the index to obtain the array element. */
6198 tmp = gfc_build_array_ref (tmp, index, NULL);
6199 break;
6201 default:
6202 gcc_unreachable ();
6203 break;
6208 /* Set the target data pointer. */
6209 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
6210 gfc_conv_descriptor_data_set (block, parm, offset);
6214 /* gfc_conv_expr_descriptor needs the string length an expression
6215 so that the size of the temporary can be obtained. This is done
6216 by adding up the string lengths of all the elements in the
6217 expression. Function with non-constant expressions have their
6218 string lengths mapped onto the actual arguments using the
6219 interface mapping machinery in trans-expr.c. */
6220 static void
6221 get_array_charlen (gfc_expr *expr, gfc_se *se)
6223 gfc_interface_mapping mapping;
6224 gfc_formal_arglist *formal;
6225 gfc_actual_arglist *arg;
6226 gfc_se tse;
6228 if (expr->ts.u.cl->length
6229 && gfc_is_constant_expr (expr->ts.u.cl->length))
6231 if (!expr->ts.u.cl->backend_decl)
6232 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6233 return;
6236 switch (expr->expr_type)
6238 case EXPR_OP:
6239 get_array_charlen (expr->value.op.op1, se);
6241 /* For parentheses the expression ts.u.cl is identical. */
6242 if (expr->value.op.op == INTRINSIC_PARENTHESES)
6243 return;
6245 expr->ts.u.cl->backend_decl =
6246 gfc_create_var (gfc_charlen_type_node, "sln");
6248 if (expr->value.op.op2)
6250 get_array_charlen (expr->value.op.op2, se);
6252 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
6254 /* Add the string lengths and assign them to the expression
6255 string length backend declaration. */
6256 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6257 fold_build2_loc (input_location, PLUS_EXPR,
6258 gfc_charlen_type_node,
6259 expr->value.op.op1->ts.u.cl->backend_decl,
6260 expr->value.op.op2->ts.u.cl->backend_decl));
6262 else
6263 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
6264 expr->value.op.op1->ts.u.cl->backend_decl);
6265 break;
6267 case EXPR_FUNCTION:
6268 if (expr->value.function.esym == NULL
6269 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
6271 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6272 break;
6275 /* Map expressions involving the dummy arguments onto the actual
6276 argument expressions. */
6277 gfc_init_interface_mapping (&mapping);
6278 formal = expr->symtree->n.sym->formal;
6279 arg = expr->value.function.actual;
6281 /* Set se = NULL in the calls to the interface mapping, to suppress any
6282 backend stuff. */
6283 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
6285 if (!arg->expr)
6286 continue;
6287 if (formal->sym)
6288 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
6291 gfc_init_se (&tse, NULL);
6293 /* Build the expression for the character length and convert it. */
6294 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
6296 gfc_add_block_to_block (&se->pre, &tse.pre);
6297 gfc_add_block_to_block (&se->post, &tse.post);
6298 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
6299 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
6300 gfc_charlen_type_node, tse.expr,
6301 build_int_cst (gfc_charlen_type_node, 0));
6302 expr->ts.u.cl->backend_decl = tse.expr;
6303 gfc_free_interface_mapping (&mapping);
6304 break;
6306 default:
6307 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
6308 break;
6313 /* Helper function to check dimensions. */
6314 static bool
6315 transposed_dims (gfc_ss *ss)
6317 int n;
6319 for (n = 0; n < ss->dimen; n++)
6320 if (ss->dim[n] != n)
6321 return true;
6322 return false;
6326 /* Convert the last ref of a scalar coarray from an AR_ELEMENT to an
6327 AR_FULL, suitable for the scalarizer. */
6329 static gfc_ss *
6330 walk_coarray (gfc_expr *e)
6332 gfc_ss *ss;
6334 gcc_assert (gfc_get_corank (e) > 0);
6336 ss = gfc_walk_expr (e);
6338 /* Fix scalar coarray. */
6339 if (ss == gfc_ss_terminator)
6341 gfc_ref *ref;
6343 ref = e->ref;
6344 while (ref)
6346 if (ref->type == REF_ARRAY
6347 && ref->u.ar.codimen > 0)
6348 break;
6350 ref = ref->next;
6353 gcc_assert (ref != NULL);
6354 if (ref->u.ar.type == AR_ELEMENT)
6355 ref->u.ar.type = AR_SECTION;
6356 ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
6359 return ss;
6363 /* Convert an array for passing as an actual argument. Expressions and
6364 vector subscripts are evaluated and stored in a temporary, which is then
6365 passed. For whole arrays the descriptor is passed. For array sections
6366 a modified copy of the descriptor is passed, but using the original data.
6368 This function is also used for array pointer assignments, and there
6369 are three cases:
6371 - se->want_pointer && !se->direct_byref
6372 EXPR is an actual argument. On exit, se->expr contains a
6373 pointer to the array descriptor.
6375 - !se->want_pointer && !se->direct_byref
6376 EXPR is an actual argument to an intrinsic function or the
6377 left-hand side of a pointer assignment. On exit, se->expr
6378 contains the descriptor for EXPR.
6380 - !se->want_pointer && se->direct_byref
6381 EXPR is the right-hand side of a pointer assignment and
6382 se->expr is the descriptor for the previously-evaluated
6383 left-hand side. The function creates an assignment from
6384 EXPR to se->expr.
6387 The se->force_tmp flag disables the non-copying descriptor optimization
6388 that is used for transpose. It may be used in cases where there is an
6389 alias between the transpose argument and another argument in the same
6390 function call. */
6392 void
6393 gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
6395 gfc_ss *ss;
6396 gfc_ss_type ss_type;
6397 gfc_ss_info *ss_info;
6398 gfc_loopinfo loop;
6399 gfc_array_info *info;
6400 int need_tmp;
6401 int n;
6402 tree tmp;
6403 tree desc;
6404 stmtblock_t block;
6405 tree start;
6406 tree offset;
6407 int full;
6408 bool subref_array_target = false;
6409 gfc_expr *arg, *ss_expr;
6411 if (se->want_coarray)
6412 ss = walk_coarray (expr);
6413 else
6414 ss = gfc_walk_expr (expr);
6416 gcc_assert (ss != NULL);
6417 gcc_assert (ss != gfc_ss_terminator);
6419 ss_info = ss->info;
6420 ss_type = ss_info->type;
6421 ss_expr = ss_info->expr;
6423 /* Special case: TRANSPOSE which needs no temporary. */
6424 while (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym
6425 && NULL != (arg = gfc_get_noncopying_intrinsic_argument (expr)))
6427 /* This is a call to transpose which has already been handled by the
6428 scalarizer, so that we just need to get its argument's descriptor. */
6429 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
6430 expr = expr->value.function.actual->expr;
6433 /* Special case things we know we can pass easily. */
6434 switch (expr->expr_type)
6436 case EXPR_VARIABLE:
6437 /* If we have a linear array section, we can pass it directly.
6438 Otherwise we need to copy it into a temporary. */
6440 gcc_assert (ss_type == GFC_SS_SECTION);
6441 gcc_assert (ss_expr == expr);
6442 info = &ss_info->data.array;
6444 /* Get the descriptor for the array. */
6445 gfc_conv_ss_descriptor (&se->pre, ss, 0);
6446 desc = info->descriptor;
6448 subref_array_target = se->direct_byref && is_subref_array (expr);
6449 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
6450 && !subref_array_target;
6452 if (se->force_tmp)
6453 need_tmp = 1;
6455 if (need_tmp)
6456 full = 0;
6457 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6459 /* Create a new descriptor if the array doesn't have one. */
6460 full = 0;
6462 else if (info->ref->u.ar.type == AR_FULL || se->descriptor_only)
6463 full = 1;
6464 else if (se->direct_byref)
6465 full = 0;
6466 else
6467 full = gfc_full_array_ref_p (info->ref, NULL);
6469 if (full && !transposed_dims (ss))
6471 if (se->direct_byref && !se->byref_noassign)
6473 /* Copy the descriptor for pointer assignments. */
6474 gfc_add_modify (&se->pre, se->expr, desc);
6476 /* Add any offsets from subreferences. */
6477 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
6478 subref_array_target, expr);
6480 else if (se->want_pointer)
6482 /* We pass full arrays directly. This means that pointers and
6483 allocatable arrays should also work. */
6484 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6486 else
6488 se->expr = desc;
6491 if (expr->ts.type == BT_CHARACTER)
6492 se->string_length = gfc_get_expr_charlen (expr);
6494 gfc_free_ss_chain (ss);
6495 return;
6497 break;
6499 case EXPR_FUNCTION:
6500 /* A transformational function return value will be a temporary
6501 array descriptor. We still need to go through the scalarizer
6502 to create the descriptor. Elemental functions are handled as
6503 arbitrary expressions, i.e. copy to a temporary. */
6505 if (se->direct_byref)
6507 gcc_assert (ss_type == GFC_SS_FUNCTION && ss_expr == expr);
6509 /* For pointer assignments pass the descriptor directly. */
6510 if (se->ss == NULL)
6511 se->ss = ss;
6512 else
6513 gcc_assert (se->ss == ss);
6514 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
6515 gfc_conv_expr (se, expr);
6516 gfc_free_ss_chain (ss);
6517 return;
6520 if (ss_expr != expr || ss_type != GFC_SS_FUNCTION)
6522 if (ss_expr != expr)
6523 /* Elemental function. */
6524 gcc_assert ((expr->value.function.esym != NULL
6525 && expr->value.function.esym->attr.elemental)
6526 || (expr->value.function.isym != NULL
6527 && expr->value.function.isym->elemental)
6528 || gfc_inline_intrinsic_function_p (expr));
6529 else
6530 gcc_assert (ss_type == GFC_SS_INTRINSIC);
6532 need_tmp = 1;
6533 if (expr->ts.type == BT_CHARACTER
6534 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
6535 get_array_charlen (expr, se);
6537 info = NULL;
6539 else
6541 /* Transformational function. */
6542 info = &ss_info->data.array;
6543 need_tmp = 0;
6545 break;
6547 case EXPR_ARRAY:
6548 /* Constant array constructors don't need a temporary. */
6549 if (ss_type == GFC_SS_CONSTRUCTOR
6550 && expr->ts.type != BT_CHARACTER
6551 && gfc_constant_array_constructor_p (expr->value.constructor))
6553 need_tmp = 0;
6554 info = &ss_info->data.array;
6556 else
6558 need_tmp = 1;
6559 info = NULL;
6561 break;
6563 default:
6564 /* Something complicated. Copy it into a temporary. */
6565 need_tmp = 1;
6566 info = NULL;
6567 break;
6570 /* If we are creating a temporary, we don't need to bother about aliases
6571 anymore. */
6572 if (need_tmp)
6573 se->force_tmp = 0;
6575 gfc_init_loopinfo (&loop);
6577 /* Associate the SS with the loop. */
6578 gfc_add_ss_to_loop (&loop, ss);
6580 /* Tell the scalarizer not to bother creating loop variables, etc. */
6581 if (!need_tmp)
6582 loop.array_parameter = 1;
6583 else
6584 /* The right-hand side of a pointer assignment mustn't use a temporary. */
6585 gcc_assert (!se->direct_byref);
6587 /* Setup the scalarizing loops and bounds. */
6588 gfc_conv_ss_startstride (&loop);
6590 if (need_tmp)
6592 if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
6593 get_array_charlen (expr, se);
6595 /* Tell the scalarizer to make a temporary. */
6596 loop.temp_ss = gfc_get_temp_ss (gfc_typenode_for_spec (&expr->ts),
6597 ((expr->ts.type == BT_CHARACTER)
6598 ? expr->ts.u.cl->backend_decl
6599 : NULL),
6600 loop.dimen);
6602 se->string_length = loop.temp_ss->info->string_length;
6603 gcc_assert (loop.temp_ss->dimen == loop.dimen);
6604 gfc_add_ss_to_loop (&loop, loop.temp_ss);
6607 gfc_conv_loop_setup (&loop, & expr->where);
6609 if (need_tmp)
6611 /* Copy into a temporary and pass that. We don't need to copy the data
6612 back because expressions and vector subscripts must be INTENT_IN. */
6613 /* TODO: Optimize passing function return values. */
6614 gfc_se lse;
6615 gfc_se rse;
6617 /* Start the copying loops. */
6618 gfc_mark_ss_chain_used (loop.temp_ss, 1);
6619 gfc_mark_ss_chain_used (ss, 1);
6620 gfc_start_scalarized_body (&loop, &block);
6622 /* Copy each data element. */
6623 gfc_init_se (&lse, NULL);
6624 gfc_copy_loopinfo_to_se (&lse, &loop);
6625 gfc_init_se (&rse, NULL);
6626 gfc_copy_loopinfo_to_se (&rse, &loop);
6628 lse.ss = loop.temp_ss;
6629 rse.ss = ss;
6631 gfc_conv_scalarized_array_ref (&lse, NULL);
6632 if (expr->ts.type == BT_CHARACTER)
6634 gfc_conv_expr (&rse, expr);
6635 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
6636 rse.expr = build_fold_indirect_ref_loc (input_location,
6637 rse.expr);
6639 else
6640 gfc_conv_expr_val (&rse, expr);
6642 gfc_add_block_to_block (&block, &rse.pre);
6643 gfc_add_block_to_block (&block, &lse.pre);
6645 lse.string_length = rse.string_length;
6646 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
6647 expr->expr_type == EXPR_VARIABLE
6648 || expr->expr_type == EXPR_ARRAY, true);
6649 gfc_add_expr_to_block (&block, tmp);
6651 /* Finish the copying loops. */
6652 gfc_trans_scalarizing_loops (&loop, &block);
6654 desc = loop.temp_ss->info->data.array.descriptor;
6656 else if (expr->expr_type == EXPR_FUNCTION && !transposed_dims (ss))
6658 desc = info->descriptor;
6659 se->string_length = ss_info->string_length;
6661 else
6663 /* We pass sections without copying to a temporary. Make a new
6664 descriptor and point it at the section we want. The loop variable
6665 limits will be the limits of the section.
6666 A function may decide to repack the array to speed up access, but
6667 we're not bothered about that here. */
6668 int dim, ndim, codim;
6669 tree parm;
6670 tree parmtype;
6671 tree stride;
6672 tree from;
6673 tree to;
6674 tree base;
6676 ndim = info->ref ? info->ref->u.ar.dimen : ss->dimen;
6678 if (se->want_coarray)
6680 gfc_array_ref *ar = &info->ref->u.ar;
6682 codim = gfc_get_corank (expr);
6683 for (n = 0; n < codim - 1; n++)
6685 /* Make sure we are not lost somehow. */
6686 gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
6688 /* Make sure the call to gfc_conv_section_startstride won't
6689 generate unnecessary code to calculate stride. */
6690 gcc_assert (ar->stride[n + ndim] == NULL);
6692 gfc_conv_section_startstride (&loop, ss, n + ndim);
6693 loop.from[n + loop.dimen] = info->start[n + ndim];
6694 loop.to[n + loop.dimen] = info->end[n + ndim];
6697 gcc_assert (n == codim - 1);
6698 evaluate_bound (&loop.pre, info->start, ar->start,
6699 info->descriptor, n + ndim, true);
6700 loop.from[n + loop.dimen] = info->start[n + ndim];
6702 else
6703 codim = 0;
6705 /* Set the string_length for a character array. */
6706 if (expr->ts.type == BT_CHARACTER)
6707 se->string_length = gfc_get_expr_charlen (expr);
6709 desc = info->descriptor;
6710 if (se->direct_byref && !se->byref_noassign)
6712 /* For pointer assignments we fill in the destination. */
6713 parm = se->expr;
6714 parmtype = TREE_TYPE (parm);
6716 else
6718 /* Otherwise make a new one. */
6719 parmtype = gfc_get_element_type (TREE_TYPE (desc));
6720 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
6721 loop.from, loop.to, 0,
6722 GFC_ARRAY_UNKNOWN, false);
6723 parm = gfc_create_var (parmtype, "parm");
6726 offset = gfc_index_zero_node;
6728 /* The following can be somewhat confusing. We have two
6729 descriptors, a new one and the original array.
6730 {parm, parmtype, dim} refer to the new one.
6731 {desc, type, n, loop} refer to the original, which maybe
6732 a descriptorless array.
6733 The bounds of the scalarization are the bounds of the section.
6734 We don't have to worry about numeric overflows when calculating
6735 the offsets because all elements are within the array data. */
6737 /* Set the dtype. */
6738 tmp = gfc_conv_descriptor_dtype (parm);
6739 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
6741 /* Set offset for assignments to pointer only to zero if it is not
6742 the full array. */
6743 if (se->direct_byref
6744 && info->ref && info->ref->u.ar.type != AR_FULL)
6745 base = gfc_index_zero_node;
6746 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6747 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
6748 else
6749 base = NULL_TREE;
6751 for (n = 0; n < ndim; n++)
6753 stride = gfc_conv_array_stride (desc, n);
6755 /* Work out the offset. */
6756 if (info->ref
6757 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6759 gcc_assert (info->subscript[n]
6760 && info->subscript[n]->info->type == GFC_SS_SCALAR);
6761 start = info->subscript[n]->info->data.scalar.value;
6763 else
6765 /* Evaluate and remember the start of the section. */
6766 start = info->start[n];
6767 stride = gfc_evaluate_now (stride, &loop.pre);
6770 tmp = gfc_conv_array_lbound (desc, n);
6771 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
6772 start, tmp);
6773 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
6774 tmp, stride);
6775 offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
6776 offset, tmp);
6778 if (info->ref
6779 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6781 /* For elemental dimensions, we only need the offset. */
6782 continue;
6785 /* Vector subscripts need copying and are handled elsewhere. */
6786 if (info->ref)
6787 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
6789 /* look for the corresponding scalarizer dimension: dim. */
6790 for (dim = 0; dim < ndim; dim++)
6791 if (ss->dim[dim] == n)
6792 break;
6794 /* loop exited early: the DIM being looked for has been found. */
6795 gcc_assert (dim < ndim);
6797 /* Set the new lower bound. */
6798 from = loop.from[dim];
6799 to = loop.to[dim];
6801 /* If we have an array section or are assigning make sure that
6802 the lower bound is 1. References to the full
6803 array should otherwise keep the original bounds. */
6804 if ((!info->ref
6805 || info->ref->u.ar.type != AR_FULL)
6806 && !integer_onep (from))
6808 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6809 gfc_array_index_type, gfc_index_one_node,
6810 from);
6811 to = fold_build2_loc (input_location, PLUS_EXPR,
6812 gfc_array_index_type, to, tmp);
6813 from = gfc_index_one_node;
6815 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
6816 gfc_rank_cst[dim], from);
6818 /* Set the new upper bound. */
6819 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
6820 gfc_rank_cst[dim], to);
6822 /* Multiply the stride by the section stride to get the
6823 total stride. */
6824 stride = fold_build2_loc (input_location, MULT_EXPR,
6825 gfc_array_index_type,
6826 stride, info->stride[n]);
6828 if (se->direct_byref
6829 && info->ref
6830 && info->ref->u.ar.type != AR_FULL)
6832 base = fold_build2_loc (input_location, MINUS_EXPR,
6833 TREE_TYPE (base), base, stride);
6835 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6837 tmp = gfc_conv_array_lbound (desc, n);
6838 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6839 TREE_TYPE (base), tmp, loop.from[dim]);
6840 tmp = fold_build2_loc (input_location, MULT_EXPR,
6841 TREE_TYPE (base), tmp,
6842 gfc_conv_array_stride (desc, n));
6843 base = fold_build2_loc (input_location, PLUS_EXPR,
6844 TREE_TYPE (base), tmp, base);
6847 /* Store the new stride. */
6848 gfc_conv_descriptor_stride_set (&loop.pre, parm,
6849 gfc_rank_cst[dim], stride);
6852 for (n = loop.dimen; n < loop.dimen + codim; n++)
6854 from = loop.from[n];
6855 to = loop.to[n];
6856 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
6857 gfc_rank_cst[n], from);
6858 if (n < loop.dimen + codim - 1)
6859 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
6860 gfc_rank_cst[n], to);
6863 if (se->data_not_needed)
6864 gfc_conv_descriptor_data_set (&loop.pre, parm,
6865 gfc_index_zero_node);
6866 else
6867 /* Point the data pointer at the 1st element in the section. */
6868 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
6869 subref_array_target, expr);
6871 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6872 && !se->data_not_needed)
6874 /* Set the offset. */
6875 gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
6877 else
6879 /* Only the callee knows what the correct offset it, so just set
6880 it to zero here. */
6881 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
6883 desc = parm;
6886 if (!se->direct_byref || se->byref_noassign)
6888 /* Get a pointer to the new descriptor. */
6889 if (se->want_pointer)
6890 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6891 else
6892 se->expr = desc;
6895 gfc_add_block_to_block (&se->pre, &loop.pre);
6896 gfc_add_block_to_block (&se->post, &loop.post);
6898 /* Cleanup the scalarizer. */
6899 gfc_cleanup_loop (&loop);
6902 /* Helper function for gfc_conv_array_parameter if array size needs to be
6903 computed. */
6905 static void
6906 array_parameter_size (tree desc, gfc_expr *expr, tree *size)
6908 tree elem;
6909 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6910 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
6911 else if (expr->rank > 1)
6912 *size = build_call_expr_loc (input_location,
6913 gfor_fndecl_size0, 1,
6914 gfc_build_addr_expr (NULL, desc));
6915 else
6917 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
6918 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
6920 *size = fold_build2_loc (input_location, MINUS_EXPR,
6921 gfc_array_index_type, ubound, lbound);
6922 *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6923 *size, gfc_index_one_node);
6924 *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
6925 *size, gfc_index_zero_node);
6927 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
6928 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6929 *size, fold_convert (gfc_array_index_type, elem));
6932 /* Convert an array for passing as an actual parameter. */
6933 /* TODO: Optimize passing g77 arrays. */
6935 void
6936 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
6937 const gfc_symbol *fsym, const char *proc_name,
6938 tree *size)
6940 tree ptr;
6941 tree desc;
6942 tree tmp = NULL_TREE;
6943 tree stmt;
6944 tree parent = DECL_CONTEXT (current_function_decl);
6945 bool full_array_var;
6946 bool this_array_result;
6947 bool contiguous;
6948 bool no_pack;
6949 bool array_constructor;
6950 bool good_allocatable;
6951 bool ultimate_ptr_comp;
6952 bool ultimate_alloc_comp;
6953 gfc_symbol *sym;
6954 stmtblock_t block;
6955 gfc_ref *ref;
6957 ultimate_ptr_comp = false;
6958 ultimate_alloc_comp = false;
6960 for (ref = expr->ref; ref; ref = ref->next)
6962 if (ref->next == NULL)
6963 break;
6965 if (ref->type == REF_COMPONENT)
6967 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
6968 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
6972 full_array_var = false;
6973 contiguous = false;
6975 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
6976 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
6978 sym = full_array_var ? expr->symtree->n.sym : NULL;
6980 /* The symbol should have an array specification. */
6981 gcc_assert (!sym || sym->as || ref->u.ar.as);
6983 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
6985 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
6986 expr->ts.u.cl->backend_decl = tmp;
6987 se->string_length = tmp;
6990 /* Is this the result of the enclosing procedure? */
6991 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
6992 if (this_array_result
6993 && (sym->backend_decl != current_function_decl)
6994 && (sym->backend_decl != parent))
6995 this_array_result = false;
6997 /* Passing address of the array if it is not pointer or assumed-shape. */
6998 if (full_array_var && g77 && !this_array_result)
7000 tmp = gfc_get_symbol_decl (sym);
7002 if (sym->ts.type == BT_CHARACTER)
7003 se->string_length = sym->ts.u.cl->backend_decl;
7005 if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)
7007 gfc_conv_expr_descriptor (se, expr);
7008 se->expr = gfc_conv_array_data (se->expr);
7009 return;
7012 if (!sym->attr.pointer
7013 && sym->as
7014 && sym->as->type != AS_ASSUMED_SHAPE
7015 && sym->as->type != AS_DEFERRED
7016 && sym->as->type != AS_ASSUMED_RANK
7017 && !sym->attr.allocatable)
7019 /* Some variables are declared directly, others are declared as
7020 pointers and allocated on the heap. */
7021 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
7022 se->expr = tmp;
7023 else
7024 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
7025 if (size)
7026 array_parameter_size (tmp, expr, size);
7027 return;
7030 if (sym->attr.allocatable)
7032 if (sym->attr.dummy || sym->attr.result)
7034 gfc_conv_expr_descriptor (se, expr);
7035 tmp = se->expr;
7037 if (size)
7038 array_parameter_size (tmp, expr, size);
7039 se->expr = gfc_conv_array_data (tmp);
7040 return;
7044 /* A convenient reduction in scope. */
7045 contiguous = g77 && !this_array_result && contiguous;
7047 /* There is no need to pack and unpack the array, if it is contiguous
7048 and not a deferred- or assumed-shape array, or if it is simply
7049 contiguous. */
7050 no_pack = ((sym && sym->as
7051 && !sym->attr.pointer
7052 && sym->as->type != AS_DEFERRED
7053 && sym->as->type != AS_ASSUMED_RANK
7054 && sym->as->type != AS_ASSUMED_SHAPE)
7056 (ref && ref->u.ar.as
7057 && ref->u.ar.as->type != AS_DEFERRED
7058 && ref->u.ar.as->type != AS_ASSUMED_RANK
7059 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
7061 gfc_is_simply_contiguous (expr, false));
7063 no_pack = contiguous && no_pack;
7065 /* Array constructors are always contiguous and do not need packing. */
7066 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
7068 /* Same is true of contiguous sections from allocatable variables. */
7069 good_allocatable = contiguous
7070 && expr->symtree
7071 && expr->symtree->n.sym->attr.allocatable;
7073 /* Or ultimate allocatable components. */
7074 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
7076 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
7078 gfc_conv_expr_descriptor (se, expr);
7079 if (expr->ts.type == BT_CHARACTER)
7080 se->string_length = expr->ts.u.cl->backend_decl;
7081 if (size)
7082 array_parameter_size (se->expr, expr, size);
7083 se->expr = gfc_conv_array_data (se->expr);
7084 return;
7087 if (this_array_result)
7089 /* Result of the enclosing function. */
7090 gfc_conv_expr_descriptor (se, expr);
7091 if (size)
7092 array_parameter_size (se->expr, expr, size);
7093 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
7095 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
7096 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
7097 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
7098 se->expr));
7100 return;
7102 else
7104 /* Every other type of array. */
7105 se->want_pointer = 1;
7106 gfc_conv_expr_descriptor (se, expr);
7107 if (size)
7108 array_parameter_size (build_fold_indirect_ref_loc (input_location,
7109 se->expr),
7110 expr, size);
7113 /* Deallocate the allocatable components of structures that are
7114 not variable. */
7115 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
7116 && expr->ts.u.derived->attr.alloc_comp
7117 && expr->expr_type != EXPR_VARIABLE)
7119 tmp = build_fold_indirect_ref_loc (input_location, se->expr);
7120 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
7122 /* The components shall be deallocated before their containing entity. */
7123 gfc_prepend_expr_to_block (&se->post, tmp);
7126 if (g77 || (fsym && fsym->attr.contiguous
7127 && !gfc_is_simply_contiguous (expr, false)))
7129 tree origptr = NULL_TREE;
7131 desc = se->expr;
7133 /* For contiguous arrays, save the original value of the descriptor. */
7134 if (!g77)
7136 origptr = gfc_create_var (pvoid_type_node, "origptr");
7137 tmp = build_fold_indirect_ref_loc (input_location, desc);
7138 tmp = gfc_conv_array_data (tmp);
7139 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7140 TREE_TYPE (origptr), origptr,
7141 fold_convert (TREE_TYPE (origptr), tmp));
7142 gfc_add_expr_to_block (&se->pre, tmp);
7145 /* Repack the array. */
7146 if (gfc_option.warn_array_temp)
7148 if (fsym)
7149 gfc_warning ("Creating array temporary at %L for argument '%s'",
7150 &expr->where, fsym->name);
7151 else
7152 gfc_warning ("Creating array temporary at %L", &expr->where);
7155 ptr = build_call_expr_loc (input_location,
7156 gfor_fndecl_in_pack, 1, desc);
7158 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7160 tmp = gfc_conv_expr_present (sym);
7161 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
7162 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
7163 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
7166 ptr = gfc_evaluate_now (ptr, &se->pre);
7168 /* Use the packed data for the actual argument, except for contiguous arrays,
7169 where the descriptor's data component is set. */
7170 if (g77)
7171 se->expr = ptr;
7172 else
7174 tmp = build_fold_indirect_ref_loc (input_location, desc);
7175 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
7178 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
7180 char * msg;
7182 if (fsym && proc_name)
7183 asprintf (&msg, "An array temporary was created for argument "
7184 "'%s' of procedure '%s'", fsym->name, proc_name);
7185 else
7186 asprintf (&msg, "An array temporary was created");
7188 tmp = build_fold_indirect_ref_loc (input_location,
7189 desc);
7190 tmp = gfc_conv_array_data (tmp);
7191 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7192 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7194 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7195 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7196 boolean_type_node,
7197 gfc_conv_expr_present (sym), tmp);
7199 gfc_trans_runtime_check (false, true, tmp, &se->pre,
7200 &expr->where, msg);
7201 free (msg);
7204 gfc_start_block (&block);
7206 /* Copy the data back. */
7207 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
7209 tmp = build_call_expr_loc (input_location,
7210 gfor_fndecl_in_unpack, 2, desc, ptr);
7211 gfc_add_expr_to_block (&block, tmp);
7214 /* Free the temporary. */
7215 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
7216 gfc_add_expr_to_block (&block, tmp);
7218 stmt = gfc_finish_block (&block);
7220 gfc_init_block (&block);
7221 /* Only if it was repacked. This code needs to be executed before the
7222 loop cleanup code. */
7223 tmp = build_fold_indirect_ref_loc (input_location,
7224 desc);
7225 tmp = gfc_conv_array_data (tmp);
7226 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7227 fold_convert (TREE_TYPE (tmp), ptr), tmp);
7229 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
7230 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7231 boolean_type_node,
7232 gfc_conv_expr_present (sym), tmp);
7234 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
7236 gfc_add_expr_to_block (&block, tmp);
7237 gfc_add_block_to_block (&block, &se->post);
7239 gfc_init_block (&se->post);
7241 /* Reset the descriptor pointer. */
7242 if (!g77)
7244 tmp = build_fold_indirect_ref_loc (input_location, desc);
7245 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
7248 gfc_add_block_to_block (&se->post, &block);
7253 /* Generate code to deallocate an array, if it is allocated. */
7255 tree
7256 gfc_trans_dealloc_allocated (tree descriptor, bool coarray)
7258 tree tmp;
7259 tree var;
7260 stmtblock_t block;
7262 gfc_start_block (&block);
7264 var = gfc_conv_descriptor_data_get (descriptor);
7265 STRIP_NOPS (var);
7267 /* Call array_deallocate with an int * present in the second argument.
7268 Although it is ignored here, it's presence ensures that arrays that
7269 are already deallocated are ignored. */
7270 tmp = gfc_deallocate_with_status (coarray ? descriptor : var, NULL_TREE,
7271 NULL_TREE, NULL_TREE, NULL_TREE, true,
7272 NULL, coarray);
7273 gfc_add_expr_to_block (&block, tmp);
7275 /* Zero the data pointer. */
7276 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7277 var, build_int_cst (TREE_TYPE (var), 0));
7278 gfc_add_expr_to_block (&block, tmp);
7280 return gfc_finish_block (&block);
7284 /* This helper function calculates the size in words of a full array. */
7286 static tree
7287 get_full_array_size (stmtblock_t *block, tree decl, int rank)
7289 tree idx;
7290 tree nelems;
7291 tree tmp;
7292 idx = gfc_rank_cst[rank - 1];
7293 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
7294 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
7295 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
7296 nelems, tmp);
7297 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
7298 tmp, gfc_index_one_node);
7299 tmp = gfc_evaluate_now (tmp, block);
7301 nelems = gfc_conv_descriptor_stride_get (decl, idx);
7302 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7303 nelems, tmp);
7304 return gfc_evaluate_now (tmp, block);
7308 /* Allocate dest to the same size as src, and copy src -> dest.
7309 If no_malloc is set, only the copy is done. */
7311 static tree
7312 duplicate_allocatable (tree dest, tree src, tree type, int rank,
7313 bool no_malloc)
7315 tree tmp;
7316 tree size;
7317 tree nelems;
7318 tree null_cond;
7319 tree null_data;
7320 stmtblock_t block;
7322 /* If the source is null, set the destination to null. Then,
7323 allocate memory to the destination. */
7324 gfc_init_block (&block);
7326 if (rank == 0)
7328 tmp = null_pointer_node;
7329 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type, dest, tmp);
7330 gfc_add_expr_to_block (&block, tmp);
7331 null_data = gfc_finish_block (&block);
7333 gfc_init_block (&block);
7334 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
7335 if (!no_malloc)
7337 tmp = gfc_call_malloc (&block, type, size);
7338 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7339 dest, fold_convert (type, tmp));
7340 gfc_add_expr_to_block (&block, tmp);
7343 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
7344 tmp = build_call_expr_loc (input_location, tmp, 3, dest, src,
7345 fold_convert (size_type_node, size));
7347 else
7349 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
7350 null_data = gfc_finish_block (&block);
7352 gfc_init_block (&block);
7353 nelems = get_full_array_size (&block, src, rank);
7354 tmp = fold_convert (gfc_array_index_type,
7355 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
7356 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
7357 nelems, tmp);
7358 if (!no_malloc)
7360 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
7361 tmp = gfc_call_malloc (&block, tmp, size);
7362 gfc_conv_descriptor_data_set (&block, dest, tmp);
7365 /* We know the temporary and the value will be the same length,
7366 so can use memcpy. */
7367 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
7368 tmp = build_call_expr_loc (input_location,
7369 tmp, 3, gfc_conv_descriptor_data_get (dest),
7370 gfc_conv_descriptor_data_get (src),
7371 fold_convert (size_type_node, size));
7374 gfc_add_expr_to_block (&block, tmp);
7375 tmp = gfc_finish_block (&block);
7377 /* Null the destination if the source is null; otherwise do
7378 the allocate and copy. */
7379 if (rank == 0)
7380 null_cond = src;
7381 else
7382 null_cond = gfc_conv_descriptor_data_get (src);
7384 null_cond = convert (pvoid_type_node, null_cond);
7385 null_cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
7386 null_cond, null_pointer_node);
7387 return build3_v (COND_EXPR, null_cond, tmp, null_data);
7391 /* Allocate dest to the same size as src, and copy data src -> dest. */
7393 tree
7394 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank)
7396 return duplicate_allocatable (dest, src, type, rank, false);
7400 /* Copy data src -> dest. */
7402 tree
7403 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
7405 return duplicate_allocatable (dest, src, type, rank, true);
7409 /* Recursively traverse an object of derived type, generating code to
7410 deallocate, nullify or copy allocatable components. This is the work horse
7411 function for the functions named in this enum. */
7413 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP,
7414 COPY_ONLY_ALLOC_COMP};
7416 static tree
7417 structure_alloc_comps (gfc_symbol * der_type, tree decl,
7418 tree dest, int rank, int purpose)
7420 gfc_component *c;
7421 gfc_loopinfo loop;
7422 stmtblock_t fnblock;
7423 stmtblock_t loopbody;
7424 stmtblock_t tmpblock;
7425 tree decl_type;
7426 tree tmp;
7427 tree comp;
7428 tree dcmp;
7429 tree nelems;
7430 tree index;
7431 tree var;
7432 tree cdecl;
7433 tree ctype;
7434 tree vref, dref;
7435 tree null_cond = NULL_TREE;
7436 bool called_dealloc_with_status;
7438 gfc_init_block (&fnblock);
7440 decl_type = TREE_TYPE (decl);
7442 if ((POINTER_TYPE_P (decl_type) && rank != 0)
7443 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
7444 decl = build_fold_indirect_ref_loc (input_location, decl);
7446 /* Just in case in gets dereferenced. */
7447 decl_type = TREE_TYPE (decl);
7449 /* If this an array of derived types with allocatable components
7450 build a loop and recursively call this function. */
7451 if (TREE_CODE (decl_type) == ARRAY_TYPE
7452 || (GFC_DESCRIPTOR_TYPE_P (decl_type) && rank != 0))
7454 tmp = gfc_conv_array_data (decl);
7455 var = build_fold_indirect_ref_loc (input_location,
7456 tmp);
7458 /* Get the number of elements - 1 and set the counter. */
7459 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
7461 /* Use the descriptor for an allocatable array. Since this
7462 is a full array reference, we only need the descriptor
7463 information from dimension = rank. */
7464 tmp = get_full_array_size (&fnblock, decl, rank);
7465 tmp = fold_build2_loc (input_location, MINUS_EXPR,
7466 gfc_array_index_type, tmp,
7467 gfc_index_one_node);
7469 null_cond = gfc_conv_descriptor_data_get (decl);
7470 null_cond = fold_build2_loc (input_location, NE_EXPR,
7471 boolean_type_node, null_cond,
7472 build_int_cst (TREE_TYPE (null_cond), 0));
7474 else
7476 /* Otherwise use the TYPE_DOMAIN information. */
7477 tmp = array_type_nelts (decl_type);
7478 tmp = fold_convert (gfc_array_index_type, tmp);
7481 /* Remember that this is, in fact, the no. of elements - 1. */
7482 nelems = gfc_evaluate_now (tmp, &fnblock);
7483 index = gfc_create_var (gfc_array_index_type, "S");
7485 /* Build the body of the loop. */
7486 gfc_init_block (&loopbody);
7488 vref = gfc_build_array_ref (var, index, NULL);
7490 if (purpose == COPY_ALLOC_COMP)
7492 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
7494 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank);
7495 gfc_add_expr_to_block (&fnblock, tmp);
7497 tmp = build_fold_indirect_ref_loc (input_location,
7498 gfc_conv_array_data (dest));
7499 dref = gfc_build_array_ref (tmp, index, NULL);
7500 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
7502 else if (purpose == COPY_ONLY_ALLOC_COMP)
7504 tmp = build_fold_indirect_ref_loc (input_location,
7505 gfc_conv_array_data (dest));
7506 dref = gfc_build_array_ref (tmp, index, NULL);
7507 tmp = structure_alloc_comps (der_type, vref, dref, rank,
7508 COPY_ALLOC_COMP);
7510 else
7511 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
7513 gfc_add_expr_to_block (&loopbody, tmp);
7515 /* Build the loop and return. */
7516 gfc_init_loopinfo (&loop);
7517 loop.dimen = 1;
7518 loop.from[0] = gfc_index_zero_node;
7519 loop.loopvar[0] = index;
7520 loop.to[0] = nelems;
7521 gfc_trans_scalarizing_loops (&loop, &loopbody);
7522 gfc_add_block_to_block (&fnblock, &loop.pre);
7524 tmp = gfc_finish_block (&fnblock);
7525 if (null_cond != NULL_TREE)
7526 tmp = build3_v (COND_EXPR, null_cond, tmp,
7527 build_empty_stmt (input_location));
7529 return tmp;
7532 /* Otherwise, act on the components or recursively call self to
7533 act on a chain of components. */
7534 for (c = der_type->components; c; c = c->next)
7536 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
7537 || c->ts.type == BT_CLASS)
7538 && c->ts.u.derived->attr.alloc_comp;
7539 cdecl = c->backend_decl;
7540 ctype = TREE_TYPE (cdecl);
7542 switch (purpose)
7544 case DEALLOCATE_ALLOC_COMP:
7546 /* gfc_deallocate_scalar_with_status calls gfc_deallocate_alloc_comp
7547 (i.e. this function) so generate all the calls and suppress the
7548 recursion from here, if necessary. */
7549 called_dealloc_with_status = false;
7550 gfc_init_block (&tmpblock);
7552 if (c->attr.allocatable
7553 && (c->attr.dimension || c->attr.codimension))
7555 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7556 decl, cdecl, NULL_TREE);
7557 tmp = gfc_trans_dealloc_allocated (comp, c->attr.codimension);
7558 gfc_add_expr_to_block (&tmpblock, tmp);
7560 else if (c->attr.allocatable)
7562 /* Allocatable scalar components. */
7563 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7564 decl, cdecl, NULL_TREE);
7566 tmp = gfc_deallocate_scalar_with_status (comp, NULL, true, NULL,
7567 c->ts);
7568 gfc_add_expr_to_block (&tmpblock, tmp);
7569 called_dealloc_with_status = true;
7571 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7572 void_type_node, comp,
7573 build_int_cst (TREE_TYPE (comp), 0));
7574 gfc_add_expr_to_block (&tmpblock, tmp);
7576 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7578 /* Allocatable CLASS components. */
7579 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7580 decl, cdecl, NULL_TREE);
7582 /* Add reference to '_data' component. */
7583 tmp = CLASS_DATA (c)->backend_decl;
7584 comp = fold_build3_loc (input_location, COMPONENT_REF,
7585 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
7587 if (GFC_DESCRIPTOR_TYPE_P(TREE_TYPE (comp)))
7588 tmp = gfc_trans_dealloc_allocated (comp,
7589 CLASS_DATA (c)->attr.codimension);
7590 else
7592 tmp = gfc_deallocate_scalar_with_status (comp, NULL_TREE, true, NULL,
7593 CLASS_DATA (c)->ts);
7594 gfc_add_expr_to_block (&tmpblock, tmp);
7595 called_dealloc_with_status = true;
7597 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7598 void_type_node, comp,
7599 build_int_cst (TREE_TYPE (comp), 0));
7601 gfc_add_expr_to_block (&tmpblock, tmp);
7604 if (cmp_has_alloc_comps
7605 && !c->attr.pointer
7606 && !called_dealloc_with_status)
7608 /* Do not deallocate the components of ultimate pointer
7609 components or iteratively call self if call has been made
7610 to gfc_trans_dealloc_allocated */
7611 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7612 decl, cdecl, NULL_TREE);
7613 rank = c->as ? c->as->rank : 0;
7614 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
7615 rank, purpose);
7616 gfc_add_expr_to_block (&fnblock, tmp);
7619 /* Now add the deallocation of this component. */
7620 gfc_add_block_to_block (&fnblock, &tmpblock);
7621 break;
7623 case NULLIFY_ALLOC_COMP:
7624 if (c->attr.pointer)
7625 continue;
7626 else if (c->attr.allocatable
7627 && (c->attr.dimension|| c->attr.codimension))
7629 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7630 decl, cdecl, NULL_TREE);
7631 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
7633 else if (c->attr.allocatable)
7635 /* Allocatable scalar components. */
7636 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7637 decl, cdecl, NULL_TREE);
7638 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7639 void_type_node, comp,
7640 build_int_cst (TREE_TYPE (comp), 0));
7641 gfc_add_expr_to_block (&fnblock, tmp);
7643 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7645 /* Allocatable CLASS components. */
7646 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7647 decl, cdecl, NULL_TREE);
7648 /* Add reference to '_data' component. */
7649 tmp = CLASS_DATA (c)->backend_decl;
7650 comp = fold_build3_loc (input_location, COMPONENT_REF,
7651 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
7652 if (GFC_DESCRIPTOR_TYPE_P(TREE_TYPE (comp)))
7653 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
7654 else
7656 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
7657 void_type_node, comp,
7658 build_int_cst (TREE_TYPE (comp), 0));
7659 gfc_add_expr_to_block (&fnblock, tmp);
7662 else if (cmp_has_alloc_comps)
7664 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
7665 decl, cdecl, NULL_TREE);
7666 rank = c->as ? c->as->rank : 0;
7667 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
7668 rank, purpose);
7669 gfc_add_expr_to_block (&fnblock, tmp);
7671 break;
7673 case COPY_ALLOC_COMP:
7674 if (c->attr.pointer)
7675 continue;
7677 /* We need source and destination components. */
7678 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
7679 cdecl, NULL_TREE);
7680 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
7681 cdecl, NULL_TREE);
7682 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
7684 if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
7686 tree ftn_tree;
7687 tree size;
7688 tree dst_data;
7689 tree src_data;
7690 tree null_data;
7692 dst_data = gfc_class_data_get (dcmp);
7693 src_data = gfc_class_data_get (comp);
7694 size = fold_convert (size_type_node, gfc_vtable_size_get (comp));
7696 if (CLASS_DATA (c)->attr.dimension)
7698 nelems = gfc_conv_descriptor_size (src_data,
7699 CLASS_DATA (c)->as->rank);
7700 src_data = gfc_conv_descriptor_data_get (src_data);
7701 dst_data = gfc_conv_descriptor_data_get (dst_data);
7703 else
7704 nelems = build_int_cst (size_type_node, 1);
7706 gfc_init_block (&tmpblock);
7708 /* We need to use CALLOC as _copy might try to free allocatable
7709 components of the destination. */
7710 ftn_tree = builtin_decl_explicit (BUILT_IN_CALLOC);
7711 tmp = build_call_expr_loc (input_location, ftn_tree, 2, nelems,
7712 size);
7713 gfc_add_modify (&tmpblock, dst_data,
7714 fold_convert (TREE_TYPE (dst_data), tmp));
7716 tmp = gfc_copy_class_to_class (comp, dcmp, nelems);
7717 gfc_add_expr_to_block (&tmpblock, tmp);
7718 tmp = gfc_finish_block (&tmpblock);
7720 gfc_init_block (&tmpblock);
7721 gfc_add_modify (&tmpblock, dst_data,
7722 fold_convert (TREE_TYPE (dst_data),
7723 null_pointer_node));
7724 null_data = gfc_finish_block (&tmpblock);
7726 null_cond = fold_build2_loc (input_location, NE_EXPR,
7727 boolean_type_node, src_data,
7728 null_pointer_node);
7730 gfc_add_expr_to_block (&fnblock, build3_v (COND_EXPR, null_cond,
7731 tmp, null_data));
7732 continue;
7735 if (c->attr.allocatable && !cmp_has_alloc_comps)
7737 rank = c->as ? c->as->rank : 0;
7738 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank);
7739 gfc_add_expr_to_block (&fnblock, tmp);
7742 if (cmp_has_alloc_comps)
7744 rank = c->as ? c->as->rank : 0;
7745 tmp = fold_convert (TREE_TYPE (dcmp), comp);
7746 gfc_add_modify (&fnblock, dcmp, tmp);
7747 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
7748 rank, purpose);
7749 gfc_add_expr_to_block (&fnblock, tmp);
7751 break;
7753 default:
7754 gcc_unreachable ();
7755 break;
7759 return gfc_finish_block (&fnblock);
7762 /* Recursively traverse an object of derived type, generating code to
7763 nullify allocatable components. */
7765 tree
7766 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
7768 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
7769 NULLIFY_ALLOC_COMP);
7773 /* Recursively traverse an object of derived type, generating code to
7774 deallocate allocatable components. */
7776 tree
7777 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
7779 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
7780 DEALLOCATE_ALLOC_COMP);
7784 /* Recursively traverse an object of derived type, generating code to
7785 copy it and its allocatable components. */
7787 tree
7788 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
7790 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
7794 /* Recursively traverse an object of derived type, generating code to
7795 copy only its allocatable components. */
7797 tree
7798 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
7800 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ONLY_ALLOC_COMP);
7804 /* Returns the value of LBOUND for an expression. This could be broken out
7805 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
7806 called by gfc_alloc_allocatable_for_assignment. */
7807 static tree
7808 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
7810 tree lbound;
7811 tree ubound;
7812 tree stride;
7813 tree cond, cond1, cond3, cond4;
7814 tree tmp;
7815 gfc_ref *ref;
7817 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
7819 tmp = gfc_rank_cst[dim];
7820 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
7821 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
7822 stride = gfc_conv_descriptor_stride_get (desc, tmp);
7823 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
7824 ubound, lbound);
7825 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
7826 stride, gfc_index_zero_node);
7827 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
7828 boolean_type_node, cond3, cond1);
7829 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
7830 stride, gfc_index_zero_node);
7831 if (assumed_size)
7832 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
7833 tmp, build_int_cst (gfc_array_index_type,
7834 expr->rank - 1));
7835 else
7836 cond = boolean_false_node;
7838 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
7839 boolean_type_node, cond3, cond4);
7840 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
7841 boolean_type_node, cond, cond1);
7843 return fold_build3_loc (input_location, COND_EXPR,
7844 gfc_array_index_type, cond,
7845 lbound, gfc_index_one_node);
7848 if (expr->expr_type == EXPR_FUNCTION)
7850 /* A conversion function, so use the argument. */
7851 gcc_assert (expr->value.function.isym
7852 && expr->value.function.isym->conversion);
7853 expr = expr->value.function.actual->expr;
7856 if (expr->expr_type == EXPR_VARIABLE)
7858 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
7859 for (ref = expr->ref; ref; ref = ref->next)
7861 if (ref->type == REF_COMPONENT
7862 && ref->u.c.component->as
7863 && ref->next
7864 && ref->next->u.ar.type == AR_FULL)
7865 tmp = TREE_TYPE (ref->u.c.component->backend_decl);
7867 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
7870 return gfc_index_one_node;
7874 /* Returns true if an expression represents an lhs that can be reallocated
7875 on assignment. */
7877 bool
7878 gfc_is_reallocatable_lhs (gfc_expr *expr)
7880 gfc_ref * ref;
7882 if (!expr->ref)
7883 return false;
7885 /* An allocatable variable. */
7886 if (expr->symtree->n.sym->attr.allocatable
7887 && expr->ref
7888 && expr->ref->type == REF_ARRAY
7889 && expr->ref->u.ar.type == AR_FULL)
7890 return true;
7892 /* All that can be left are allocatable components. */
7893 if ((expr->symtree->n.sym->ts.type != BT_DERIVED
7894 && expr->symtree->n.sym->ts.type != BT_CLASS)
7895 || !expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
7896 return false;
7898 /* Find a component ref followed by an array reference. */
7899 for (ref = expr->ref; ref; ref = ref->next)
7900 if (ref->next
7901 && ref->type == REF_COMPONENT
7902 && ref->next->type == REF_ARRAY
7903 && !ref->next->next)
7904 break;
7906 if (!ref)
7907 return false;
7909 /* Return true if valid reallocatable lhs. */
7910 if (ref->u.c.component->attr.allocatable
7911 && ref->next->u.ar.type == AR_FULL)
7912 return true;
7914 return false;
7918 /* Allocate the lhs of an assignment to an allocatable array, otherwise
7919 reallocate it. */
7921 tree
7922 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
7923 gfc_expr *expr1,
7924 gfc_expr *expr2)
7926 stmtblock_t realloc_block;
7927 stmtblock_t alloc_block;
7928 stmtblock_t fblock;
7929 gfc_ss *rss;
7930 gfc_ss *lss;
7931 gfc_array_info *linfo;
7932 tree realloc_expr;
7933 tree alloc_expr;
7934 tree size1;
7935 tree size2;
7936 tree array1;
7937 tree cond;
7938 tree tmp;
7939 tree tmp2;
7940 tree lbound;
7941 tree ubound;
7942 tree desc;
7943 tree desc2;
7944 tree offset;
7945 tree jump_label1;
7946 tree jump_label2;
7947 tree neq_size;
7948 tree lbd;
7949 int n;
7950 int dim;
7951 gfc_array_spec * as;
7953 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
7954 Find the lhs expression in the loop chain and set expr1 and
7955 expr2 accordingly. */
7956 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
7958 expr2 = expr1;
7959 /* Find the ss for the lhs. */
7960 lss = loop->ss;
7961 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
7962 if (lss->info->expr && lss->info->expr->expr_type == EXPR_VARIABLE)
7963 break;
7964 if (lss == gfc_ss_terminator)
7965 return NULL_TREE;
7966 expr1 = lss->info->expr;
7969 /* Bail out if this is not a valid allocate on assignment. */
7970 if (!gfc_is_reallocatable_lhs (expr1)
7971 || (expr2 && !expr2->rank))
7972 return NULL_TREE;
7974 /* Find the ss for the lhs. */
7975 lss = loop->ss;
7976 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
7977 if (lss->info->expr == expr1)
7978 break;
7980 if (lss == gfc_ss_terminator)
7981 return NULL_TREE;
7983 linfo = &lss->info->data.array;
7985 /* Find an ss for the rhs. For operator expressions, we see the
7986 ss's for the operands. Any one of these will do. */
7987 rss = loop->ss;
7988 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
7989 if (rss->info->expr != expr1 && rss != loop->temp_ss)
7990 break;
7992 if (expr2 && rss == gfc_ss_terminator)
7993 return NULL_TREE;
7995 gfc_start_block (&fblock);
7997 /* Since the lhs is allocatable, this must be a descriptor type.
7998 Get the data and array size. */
7999 desc = linfo->descriptor;
8000 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
8001 array1 = gfc_conv_descriptor_data_get (desc);
8003 /* 7.4.1.3 "If variable is an allocated allocatable variable, it is
8004 deallocated if expr is an array of different shape or any of the
8005 corresponding length type parameter values of variable and expr
8006 differ." This assures F95 compatibility. */
8007 jump_label1 = gfc_build_label_decl (NULL_TREE);
8008 jump_label2 = gfc_build_label_decl (NULL_TREE);
8010 /* Allocate if data is NULL. */
8011 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
8012 array1, build_int_cst (TREE_TYPE (array1), 0));
8013 tmp = build3_v (COND_EXPR, cond,
8014 build1_v (GOTO_EXPR, jump_label1),
8015 build_empty_stmt (input_location));
8016 gfc_add_expr_to_block (&fblock, tmp);
8018 /* Get arrayspec if expr is a full array. */
8019 if (expr2 && expr2->expr_type == EXPR_FUNCTION
8020 && expr2->value.function.isym
8021 && expr2->value.function.isym->conversion)
8023 /* For conversion functions, take the arg. */
8024 gfc_expr *arg = expr2->value.function.actual->expr;
8025 as = gfc_get_full_arrayspec_from_expr (arg);
8027 else if (expr2)
8028 as = gfc_get_full_arrayspec_from_expr (expr2);
8029 else
8030 as = NULL;
8032 /* If the lhs shape is not the same as the rhs jump to setting the
8033 bounds and doing the reallocation....... */
8034 for (n = 0; n < expr1->rank; n++)
8036 /* Check the shape. */
8037 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
8038 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
8039 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8040 gfc_array_index_type,
8041 loop->to[n], loop->from[n]);
8042 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8043 gfc_array_index_type,
8044 tmp, lbound);
8045 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8046 gfc_array_index_type,
8047 tmp, ubound);
8048 cond = fold_build2_loc (input_location, NE_EXPR,
8049 boolean_type_node,
8050 tmp, gfc_index_zero_node);
8051 tmp = build3_v (COND_EXPR, cond,
8052 build1_v (GOTO_EXPR, jump_label1),
8053 build_empty_stmt (input_location));
8054 gfc_add_expr_to_block (&fblock, tmp);
8057 /* ....else jump past the (re)alloc code. */
8058 tmp = build1_v (GOTO_EXPR, jump_label2);
8059 gfc_add_expr_to_block (&fblock, tmp);
8061 /* Add the label to start automatic (re)allocation. */
8062 tmp = build1_v (LABEL_EXPR, jump_label1);
8063 gfc_add_expr_to_block (&fblock, tmp);
8065 size1 = gfc_conv_descriptor_size (desc, expr1->rank);
8067 /* Get the rhs size. Fix both sizes. */
8068 if (expr2)
8069 desc2 = rss->info->data.array.descriptor;
8070 else
8071 desc2 = NULL_TREE;
8072 size2 = gfc_index_one_node;
8073 for (n = 0; n < expr2->rank; n++)
8075 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8076 gfc_array_index_type,
8077 loop->to[n], loop->from[n]);
8078 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8079 gfc_array_index_type,
8080 tmp, gfc_index_one_node);
8081 size2 = fold_build2_loc (input_location, MULT_EXPR,
8082 gfc_array_index_type,
8083 tmp, size2);
8086 size1 = gfc_evaluate_now (size1, &fblock);
8087 size2 = gfc_evaluate_now (size2, &fblock);
8089 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
8090 size1, size2);
8091 neq_size = gfc_evaluate_now (cond, &fblock);
8094 /* Now modify the lhs descriptor and the associated scalarizer
8095 variables. F2003 7.4.1.3: "If variable is or becomes an
8096 unallocated allocatable variable, then it is allocated with each
8097 deferred type parameter equal to the corresponding type parameters
8098 of expr , with the shape of expr , and with each lower bound equal
8099 to the corresponding element of LBOUND(expr)."
8100 Reuse size1 to keep a dimension-by-dimension track of the
8101 stride of the new array. */
8102 size1 = gfc_index_one_node;
8103 offset = gfc_index_zero_node;
8105 for (n = 0; n < expr2->rank; n++)
8107 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8108 gfc_array_index_type,
8109 loop->to[n], loop->from[n]);
8110 tmp = fold_build2_loc (input_location, PLUS_EXPR,
8111 gfc_array_index_type,
8112 tmp, gfc_index_one_node);
8114 lbound = gfc_index_one_node;
8115 ubound = tmp;
8117 if (as)
8119 lbd = get_std_lbound (expr2, desc2, n,
8120 as->type == AS_ASSUMED_SIZE);
8121 ubound = fold_build2_loc (input_location,
8122 MINUS_EXPR,
8123 gfc_array_index_type,
8124 ubound, lbound);
8125 ubound = fold_build2_loc (input_location,
8126 PLUS_EXPR,
8127 gfc_array_index_type,
8128 ubound, lbd);
8129 lbound = lbd;
8132 gfc_conv_descriptor_lbound_set (&fblock, desc,
8133 gfc_rank_cst[n],
8134 lbound);
8135 gfc_conv_descriptor_ubound_set (&fblock, desc,
8136 gfc_rank_cst[n],
8137 ubound);
8138 gfc_conv_descriptor_stride_set (&fblock, desc,
8139 gfc_rank_cst[n],
8140 size1);
8141 lbound = gfc_conv_descriptor_lbound_get (desc,
8142 gfc_rank_cst[n]);
8143 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
8144 gfc_array_index_type,
8145 lbound, size1);
8146 offset = fold_build2_loc (input_location, MINUS_EXPR,
8147 gfc_array_index_type,
8148 offset, tmp2);
8149 size1 = fold_build2_loc (input_location, MULT_EXPR,
8150 gfc_array_index_type,
8151 tmp, size1);
8154 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
8155 the array offset is saved and the info.offset is used for a
8156 running offset. Use the saved_offset instead. */
8157 tmp = gfc_conv_descriptor_offset (desc);
8158 gfc_add_modify (&fblock, tmp, offset);
8159 if (linfo->saved_offset
8160 && TREE_CODE (linfo->saved_offset) == VAR_DECL)
8161 gfc_add_modify (&fblock, linfo->saved_offset, tmp);
8163 /* Now set the deltas for the lhs. */
8164 for (n = 0; n < expr1->rank; n++)
8166 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
8167 dim = lss->dim[n];
8168 tmp = fold_build2_loc (input_location, MINUS_EXPR,
8169 gfc_array_index_type, tmp,
8170 loop->from[dim]);
8171 if (linfo->delta[dim]
8172 && TREE_CODE (linfo->delta[dim]) == VAR_DECL)
8173 gfc_add_modify (&fblock, linfo->delta[dim], tmp);
8176 /* Get the new lhs size in bytes. */
8177 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
8179 tmp = expr2->ts.u.cl->backend_decl;
8180 gcc_assert (expr1->ts.u.cl->backend_decl);
8181 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
8182 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
8184 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
8186 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
8187 tmp = fold_build2_loc (input_location, MULT_EXPR,
8188 gfc_array_index_type, tmp,
8189 expr1->ts.u.cl->backend_decl);
8191 else
8192 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
8193 tmp = fold_convert (gfc_array_index_type, tmp);
8194 size2 = fold_build2_loc (input_location, MULT_EXPR,
8195 gfc_array_index_type,
8196 tmp, size2);
8197 size2 = fold_convert (size_type_node, size2);
8198 size2 = gfc_evaluate_now (size2, &fblock);
8200 /* Realloc expression. Note that the scalarizer uses desc.data
8201 in the array reference - (*desc.data)[<element>]. */
8202 gfc_init_block (&realloc_block);
8203 tmp = build_call_expr_loc (input_location,
8204 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
8205 fold_convert (pvoid_type_node, array1),
8206 size2);
8207 gfc_conv_descriptor_data_set (&realloc_block,
8208 desc, tmp);
8209 realloc_expr = gfc_finish_block (&realloc_block);
8211 /* Only reallocate if sizes are different. */
8212 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
8213 build_empty_stmt (input_location));
8214 realloc_expr = tmp;
8217 /* Malloc expression. */
8218 gfc_init_block (&alloc_block);
8219 tmp = build_call_expr_loc (input_location,
8220 builtin_decl_explicit (BUILT_IN_MALLOC),
8221 1, size2);
8222 gfc_conv_descriptor_data_set (&alloc_block,
8223 desc, tmp);
8224 tmp = gfc_conv_descriptor_dtype (desc);
8225 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
8226 alloc_expr = gfc_finish_block (&alloc_block);
8228 /* Malloc if not allocated; realloc otherwise. */
8229 tmp = build_int_cst (TREE_TYPE (array1), 0);
8230 cond = fold_build2_loc (input_location, EQ_EXPR,
8231 boolean_type_node,
8232 array1, tmp);
8233 tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
8234 gfc_add_expr_to_block (&fblock, tmp);
8236 /* Make sure that the scalarizer data pointer is updated. */
8237 if (linfo->data
8238 && TREE_CODE (linfo->data) == VAR_DECL)
8240 tmp = gfc_conv_descriptor_data_get (desc);
8241 gfc_add_modify (&fblock, linfo->data, tmp);
8244 /* Add the exit label. */
8245 tmp = build1_v (LABEL_EXPR, jump_label2);
8246 gfc_add_expr_to_block (&fblock, tmp);
8248 return gfc_finish_block (&fblock);
8252 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
8253 Do likewise, recursively if necessary, with the allocatable components of
8254 derived types. */
8256 void
8257 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
8259 tree type;
8260 tree tmp;
8261 tree descriptor;
8262 stmtblock_t init;
8263 stmtblock_t cleanup;
8264 locus loc;
8265 int rank;
8266 bool sym_has_alloc_comp;
8268 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
8269 || sym->ts.type == BT_CLASS)
8270 && sym->ts.u.derived->attr.alloc_comp;
8272 /* Make sure the frontend gets these right. */
8273 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
8274 fatal_error ("Possible front-end bug: Deferred array size without pointer, "
8275 "allocatable attribute or derived type without allocatable "
8276 "components.");
8278 gfc_save_backend_locus (&loc);
8279 gfc_set_backend_locus (&sym->declared_at);
8280 gfc_init_block (&init);
8282 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
8283 || TREE_CODE (sym->backend_decl) == PARM_DECL);
8285 if (sym->ts.type == BT_CHARACTER
8286 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
8288 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
8289 gfc_trans_vla_type_sizes (sym, &init);
8292 /* Dummy, use associated and result variables don't need anything special. */
8293 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
8295 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
8296 gfc_restore_backend_locus (&loc);
8297 return;
8300 descriptor = sym->backend_decl;
8302 /* Although static, derived types with default initializers and
8303 allocatable components must not be nulled wholesale; instead they
8304 are treated component by component. */
8305 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
8307 /* SAVEd variables are not freed on exit. */
8308 gfc_trans_static_array_pointer (sym);
8310 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
8311 gfc_restore_backend_locus (&loc);
8312 return;
8315 /* Get the descriptor type. */
8316 type = TREE_TYPE (sym->backend_decl);
8318 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
8320 if (!sym->attr.save
8321 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
8323 if (sym->value == NULL
8324 || !gfc_has_default_initializer (sym->ts.u.derived))
8326 rank = sym->as ? sym->as->rank : 0;
8327 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
8328 descriptor, rank);
8329 gfc_add_expr_to_block (&init, tmp);
8331 else
8332 gfc_init_default_dt (sym, &init, false);
8335 else if (!GFC_DESCRIPTOR_TYPE_P (type))
8337 /* If the backend_decl is not a descriptor, we must have a pointer
8338 to one. */
8339 descriptor = build_fold_indirect_ref_loc (input_location,
8340 sym->backend_decl);
8341 type = TREE_TYPE (descriptor);
8344 /* NULLIFY the data pointer. */
8345 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
8346 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
8348 gfc_restore_backend_locus (&loc);
8349 gfc_init_block (&cleanup);
8351 /* Allocatable arrays need to be freed when they go out of scope.
8352 The allocatable components of pointers must not be touched. */
8353 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
8354 && !sym->attr.pointer && !sym->attr.save)
8356 int rank;
8357 rank = sym->as ? sym->as->rank : 0;
8358 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
8359 gfc_add_expr_to_block (&cleanup, tmp);
8362 if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
8363 && !sym->attr.save && !sym->attr.result)
8365 tmp = gfc_trans_dealloc_allocated (sym->backend_decl,
8366 sym->attr.codimension);
8367 gfc_add_expr_to_block (&cleanup, tmp);
8370 gfc_add_init_cleanup (block, gfc_finish_block (&init),
8371 gfc_finish_block (&cleanup));
8374 /************ Expression Walking Functions ******************/
8376 /* Walk a variable reference.
8378 Possible extension - multiple component subscripts.
8379 x(:,:) = foo%a(:)%b(:)
8380 Transforms to
8381 forall (i=..., j=...)
8382 x(i,j) = foo%a(j)%b(i)
8383 end forall
8384 This adds a fair amount of complexity because you need to deal with more
8385 than one ref. Maybe handle in a similar manner to vector subscripts.
8386 Maybe not worth the effort. */
8389 static gfc_ss *
8390 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
8392 gfc_ref *ref;
8394 for (ref = expr->ref; ref; ref = ref->next)
8395 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
8396 break;
8398 return gfc_walk_array_ref (ss, expr, ref);
8402 gfc_ss *
8403 gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
8405 gfc_array_ref *ar;
8406 gfc_ss *newss;
8407 int n;
8409 for (; ref; ref = ref->next)
8411 if (ref->type == REF_SUBSTRING)
8413 ss = gfc_get_scalar_ss (ss, ref->u.ss.start);
8414 ss = gfc_get_scalar_ss (ss, ref->u.ss.end);
8417 /* We're only interested in array sections from now on. */
8418 if (ref->type != REF_ARRAY)
8419 continue;
8421 ar = &ref->u.ar;
8423 switch (ar->type)
8425 case AR_ELEMENT:
8426 for (n = ar->dimen - 1; n >= 0; n--)
8427 ss = gfc_get_scalar_ss (ss, ar->start[n]);
8428 break;
8430 case AR_FULL:
8431 newss = gfc_get_array_ss (ss, expr, ar->as->rank, GFC_SS_SECTION);
8432 newss->info->data.array.ref = ref;
8434 /* Make sure array is the same as array(:,:), this way
8435 we don't need to special case all the time. */
8436 ar->dimen = ar->as->rank;
8437 for (n = 0; n < ar->dimen; n++)
8439 ar->dimen_type[n] = DIMEN_RANGE;
8441 gcc_assert (ar->start[n] == NULL);
8442 gcc_assert (ar->end[n] == NULL);
8443 gcc_assert (ar->stride[n] == NULL);
8445 ss = newss;
8446 break;
8448 case AR_SECTION:
8449 newss = gfc_get_array_ss (ss, expr, 0, GFC_SS_SECTION);
8450 newss->info->data.array.ref = ref;
8452 /* We add SS chains for all the subscripts in the section. */
8453 for (n = 0; n < ar->dimen; n++)
8455 gfc_ss *indexss;
8457 switch (ar->dimen_type[n])
8459 case DIMEN_ELEMENT:
8460 /* Add SS for elemental (scalar) subscripts. */
8461 gcc_assert (ar->start[n]);
8462 indexss = gfc_get_scalar_ss (gfc_ss_terminator, ar->start[n]);
8463 indexss->loop_chain = gfc_ss_terminator;
8464 newss->info->data.array.subscript[n] = indexss;
8465 break;
8467 case DIMEN_RANGE:
8468 /* We don't add anything for sections, just remember this
8469 dimension for later. */
8470 newss->dim[newss->dimen] = n;
8471 newss->dimen++;
8472 break;
8474 case DIMEN_VECTOR:
8475 /* Create a GFC_SS_VECTOR index in which we can store
8476 the vector's descriptor. */
8477 indexss = gfc_get_array_ss (gfc_ss_terminator, ar->start[n],
8478 1, GFC_SS_VECTOR);
8479 indexss->loop_chain = gfc_ss_terminator;
8480 newss->info->data.array.subscript[n] = indexss;
8481 newss->dim[newss->dimen] = n;
8482 newss->dimen++;
8483 break;
8485 default:
8486 /* We should know what sort of section it is by now. */
8487 gcc_unreachable ();
8490 /* We should have at least one non-elemental dimension,
8491 unless we are creating a descriptor for a (scalar) coarray. */
8492 gcc_assert (newss->dimen > 0
8493 || newss->info->data.array.ref->u.ar.as->corank > 0);
8494 ss = newss;
8495 break;
8497 default:
8498 /* We should know what sort of section it is by now. */
8499 gcc_unreachable ();
8503 return ss;
8507 /* Walk an expression operator. If only one operand of a binary expression is
8508 scalar, we must also add the scalar term to the SS chain. */
8510 static gfc_ss *
8511 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
8513 gfc_ss *head;
8514 gfc_ss *head2;
8516 head = gfc_walk_subexpr (ss, expr->value.op.op1);
8517 if (expr->value.op.op2 == NULL)
8518 head2 = head;
8519 else
8520 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
8522 /* All operands are scalar. Pass back and let the caller deal with it. */
8523 if (head2 == ss)
8524 return head2;
8526 /* All operands require scalarization. */
8527 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
8528 return head2;
8530 /* One of the operands needs scalarization, the other is scalar.
8531 Create a gfc_ss for the scalar expression. */
8532 if (head == ss)
8534 /* First operand is scalar. We build the chain in reverse order, so
8535 add the scalar SS after the second operand. */
8536 head = head2;
8537 while (head && head->next != ss)
8538 head = head->next;
8539 /* Check we haven't somehow broken the chain. */
8540 gcc_assert (head);
8541 head->next = gfc_get_scalar_ss (ss, expr->value.op.op1);
8543 else /* head2 == head */
8545 gcc_assert (head2 == head);
8546 /* Second operand is scalar. */
8547 head2 = gfc_get_scalar_ss (head2, expr->value.op.op2);
8550 return head2;
8554 /* Reverse a SS chain. */
8556 gfc_ss *
8557 gfc_reverse_ss (gfc_ss * ss)
8559 gfc_ss *next;
8560 gfc_ss *head;
8562 gcc_assert (ss != NULL);
8564 head = gfc_ss_terminator;
8565 while (ss != gfc_ss_terminator)
8567 next = ss->next;
8568 /* Check we didn't somehow break the chain. */
8569 gcc_assert (next != NULL);
8570 ss->next = head;
8571 head = ss;
8572 ss = next;
8575 return (head);
8579 /* Given an expression referring to a procedure, return the symbol of its
8580 interface. We can't get the procedure symbol directly as we have to handle
8581 the case of (deferred) type-bound procedures. */
8583 gfc_symbol *
8584 gfc_get_proc_ifc_for_expr (gfc_expr *procedure_ref)
8586 gfc_symbol *sym;
8587 gfc_ref *ref;
8589 if (procedure_ref == NULL)
8590 return NULL;
8592 /* Normal procedure case. */
8593 sym = procedure_ref->symtree->n.sym;
8595 /* Typebound procedure case. */
8596 for (ref = procedure_ref->ref; ref; ref = ref->next)
8598 if (ref->type == REF_COMPONENT
8599 && ref->u.c.component->attr.proc_pointer)
8600 sym = ref->u.c.component->ts.interface;
8601 else
8602 sym = NULL;
8605 return sym;
8609 /* Walk the arguments of an elemental function.
8610 PROC_EXPR is used to check whether an argument is permitted to be absent. If
8611 it is NULL, we don't do the check and the argument is assumed to be present.
8614 gfc_ss *
8615 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
8616 gfc_symbol *proc_ifc, gfc_ss_type type)
8618 gfc_formal_arglist *dummy_arg;
8619 int scalar;
8620 gfc_ss *head;
8621 gfc_ss *tail;
8622 gfc_ss *newss;
8624 head = gfc_ss_terminator;
8625 tail = NULL;
8627 if (proc_ifc)
8628 dummy_arg = proc_ifc->formal;
8629 else
8630 dummy_arg = NULL;
8632 scalar = 1;
8633 for (; arg; arg = arg->next)
8635 if (!arg->expr || arg->expr->expr_type == EXPR_NULL)
8636 continue;
8638 newss = gfc_walk_subexpr (head, arg->expr);
8639 if (newss == head)
8641 /* Scalar argument. */
8642 gcc_assert (type == GFC_SS_SCALAR || type == GFC_SS_REFERENCE);
8643 newss = gfc_get_scalar_ss (head, arg->expr);
8644 newss->info->type = type;
8647 else
8648 scalar = 0;
8650 if (dummy_arg != NULL
8651 && dummy_arg->sym->attr.optional
8652 && arg->expr->expr_type == EXPR_VARIABLE
8653 && (gfc_expr_attr (arg->expr).optional
8654 || gfc_expr_attr (arg->expr).allocatable
8655 || gfc_expr_attr (arg->expr).pointer))
8656 newss->info->can_be_null_ref = true;
8658 head = newss;
8659 if (!tail)
8661 tail = head;
8662 while (tail->next != gfc_ss_terminator)
8663 tail = tail->next;
8666 if (dummy_arg != NULL)
8667 dummy_arg = dummy_arg->next;
8670 if (scalar)
8672 /* If all the arguments are scalar we don't need the argument SS. */
8673 gfc_free_ss_chain (head);
8674 /* Pass it back. */
8675 return ss;
8678 /* Add it onto the existing chain. */
8679 tail->next = ss;
8680 return head;
8684 /* Walk a function call. Scalar functions are passed back, and taken out of
8685 scalarization loops. For elemental functions we walk their arguments.
8686 The result of functions returning arrays is stored in a temporary outside
8687 the loop, so that the function is only called once. Hence we do not need
8688 to walk their arguments. */
8690 static gfc_ss *
8691 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
8693 gfc_intrinsic_sym *isym;
8694 gfc_symbol *sym;
8695 gfc_component *comp = NULL;
8697 isym = expr->value.function.isym;
8699 /* Handle intrinsic functions separately. */
8700 if (isym)
8701 return gfc_walk_intrinsic_function (ss, expr, isym);
8703 sym = expr->value.function.esym;
8704 if (!sym)
8705 sym = expr->symtree->n.sym;
8707 /* A function that returns arrays. */
8708 comp = gfc_get_proc_ptr_comp (expr);
8709 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
8710 || (comp && comp->attr.dimension))
8711 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_FUNCTION);
8713 /* Walk the parameters of an elemental function. For now we always pass
8714 by reference. */
8715 if (sym->attr.elemental || (comp && comp->attr.elemental))
8716 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
8717 gfc_get_proc_ifc_for_expr (expr),
8718 GFC_SS_REFERENCE);
8720 /* Scalar functions are OK as these are evaluated outside the scalarization
8721 loop. Pass back and let the caller deal with it. */
8722 return ss;
8726 /* An array temporary is constructed for array constructors. */
8728 static gfc_ss *
8729 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
8731 return gfc_get_array_ss (ss, expr, expr->rank, GFC_SS_CONSTRUCTOR);
8735 /* Walk an expression. Add walked expressions to the head of the SS chain.
8736 A wholly scalar expression will not be added. */
8738 gfc_ss *
8739 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
8741 gfc_ss *head;
8743 switch (expr->expr_type)
8745 case EXPR_VARIABLE:
8746 head = gfc_walk_variable_expr (ss, expr);
8747 return head;
8749 case EXPR_OP:
8750 head = gfc_walk_op_expr (ss, expr);
8751 return head;
8753 case EXPR_FUNCTION:
8754 head = gfc_walk_function_expr (ss, expr);
8755 return head;
8757 case EXPR_CONSTANT:
8758 case EXPR_NULL:
8759 case EXPR_STRUCTURE:
8760 /* Pass back and let the caller deal with it. */
8761 break;
8763 case EXPR_ARRAY:
8764 head = gfc_walk_array_constructor (ss, expr);
8765 return head;
8767 case EXPR_SUBSTRING:
8768 /* Pass back and let the caller deal with it. */
8769 break;
8771 default:
8772 internal_error ("bad expression type during walk (%d)",
8773 expr->expr_type);
8775 return ss;
8779 /* Entry point for expression walking.
8780 A return value equal to the passed chain means this is
8781 a scalar expression. It is up to the caller to take whatever action is
8782 necessary to translate these. */
8784 gfc_ss *
8785 gfc_walk_expr (gfc_expr * expr)
8787 gfc_ss *res;
8789 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
8790 return gfc_reverse_ss (res);