Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / gcc / fortran / trans-array.c
blob7ea84c75d8f05180aebcc31dac4dfb00ba17b089
1 /* Array translation routines
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* trans-array.c-- Various array related code, including scalarization,
24 allocation, initialization and other support routines. */
26 /* How the scalarizer works.
27 In gfortran, array expressions use the same core routines as scalar
28 expressions.
29 First, a Scalarization State (SS) chain is built. This is done by walking
30 the expression tree, and building a linear list of the terms in the
31 expression. As the tree is walked, scalar subexpressions are translated.
33 The scalarization parameters are stored in a gfc_loopinfo structure.
34 First the start and stride of each term is calculated by
35 gfc_conv_ss_startstride. During this process the expressions for the array
36 descriptors and data pointers are also translated.
38 If the expression is an assignment, we must then resolve any dependencies.
39 In fortran all the rhs values of an assignment must be evaluated before
40 any assignments take place. This can require a temporary array to store the
41 values. We also require a temporary when we are passing array expressions
42 or vector subscripts as procedure parameters.
44 Array sections are passed without copying to a temporary. These use the
45 scalarizer to determine the shape of the section. The flag
46 loop->array_parameter tells the scalarizer that the actual values and loop
47 variables will not be required.
49 The function gfc_conv_loop_setup generates the scalarization setup code.
50 It determines the range of the scalarizing loop variables. If a temporary
51 is required, this is created and initialized. Code for scalar expressions
52 taken outside the loop is also generated at this time. Next the offset and
53 scaling required to translate from loop variables to array indices for each
54 term is calculated.
56 A call to gfc_start_scalarized_body marks the start of the scalarized
57 expression. This creates a scope and declares the loop variables. Before
58 calling this gfc_make_ss_chain_used must be used to indicate which terms
59 will be used inside this loop.
61 The scalar gfc_conv_* functions are then used to build the main body of the
62 scalarization loop. Scalarization loop variables and precalculated scalar
63 values are automatically substituted. Note that gfc_advance_se_ss_chain
64 must be used, rather than changing the se->ss directly.
66 For assignment expressions requiring a temporary two sub loops are
67 generated. The first stores the result of the expression in the temporary,
68 the second copies it to the result. A call to
69 gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
70 the start of the copying loop. The temporary may be less than full rank.
72 Finally gfc_trans_scalarizing_loops is called to generate the implicit do
73 loops. The loops are added to the pre chain of the loopinfo. The post
74 chain may still contain cleanup code.
76 After the loop code has been added into its parent scope gfc_cleanup_loop
77 is called to free all the SS allocated by the scalarizer. */
79 #include "config.h"
80 #include "system.h"
81 #include "coretypes.h"
82 #include "tree.h"
83 #include "diagnostic-core.h" /* For internal_error/fatal_error. */
84 #include "flags.h"
85 #include "gfortran.h"
86 #include "constructor.h"
87 #include "trans.h"
88 #include "trans-stmt.h"
89 #include "trans-types.h"
90 #include "trans-array.h"
91 #include "trans-const.h"
92 #include "dependency.h"
94 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
96 /* The contents of this structure aren't actually used, just the address. */
97 static gfc_ss gfc_ss_terminator_var;
98 gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
101 static tree
102 gfc_array_dataptr_type (tree desc)
104 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
108 /* Build expressions to access the members of an array descriptor.
109 It's surprisingly easy to mess up here, so never access
110 an array descriptor by "brute force", always use these
111 functions. This also avoids problems if we change the format
112 of an array descriptor.
114 To understand these magic numbers, look at the comments
115 before gfc_build_array_type() in trans-types.c.
117 The code within these defines should be the only code which knows the format
118 of an array descriptor.
120 Any code just needing to read obtain the bounds of an array should use
121 gfc_conv_array_* rather than the following functions as these will return
122 know constant values, and work with arrays which do not have descriptors.
124 Don't forget to #undef these! */
126 #define DATA_FIELD 0
127 #define OFFSET_FIELD 1
128 #define DTYPE_FIELD 2
129 #define DIMENSION_FIELD 3
131 #define STRIDE_SUBFIELD 0
132 #define LBOUND_SUBFIELD 1
133 #define UBOUND_SUBFIELD 2
135 /* This provides READ-ONLY access to the data field. The field itself
136 doesn't have the proper type. */
138 tree
139 gfc_conv_descriptor_data_get (tree desc)
141 tree field, type, t;
143 type = TREE_TYPE (desc);
144 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
146 field = TYPE_FIELDS (type);
147 gcc_assert (DATA_FIELD == 0);
149 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
150 field, NULL_TREE);
151 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
153 return t;
156 /* This provides WRITE access to the data field.
158 TUPLES_P is true if we are generating tuples.
160 This function gets called through the following macros:
161 gfc_conv_descriptor_data_set
162 gfc_conv_descriptor_data_set. */
164 void
165 gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
167 tree field, type, t;
169 type = TREE_TYPE (desc);
170 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
172 field = TYPE_FIELDS (type);
173 gcc_assert (DATA_FIELD == 0);
175 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
176 field, NULL_TREE);
177 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
181 /* This provides address access to the data field. This should only be
182 used by array allocation, passing this on to the runtime. */
184 tree
185 gfc_conv_descriptor_data_addr (tree desc)
187 tree field, type, t;
189 type = TREE_TYPE (desc);
190 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
192 field = TYPE_FIELDS (type);
193 gcc_assert (DATA_FIELD == 0);
195 t = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), desc,
196 field, NULL_TREE);
197 return gfc_build_addr_expr (NULL_TREE, t);
200 static tree
201 gfc_conv_descriptor_offset (tree desc)
203 tree type;
204 tree field;
206 type = TREE_TYPE (desc);
207 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
209 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
210 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
212 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
213 desc, field, NULL_TREE);
216 tree
217 gfc_conv_descriptor_offset_get (tree desc)
219 return gfc_conv_descriptor_offset (desc);
222 void
223 gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
224 tree value)
226 tree t = gfc_conv_descriptor_offset (desc);
227 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
231 tree
232 gfc_conv_descriptor_dtype (tree desc)
234 tree field;
235 tree type;
237 type = TREE_TYPE (desc);
238 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
240 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
241 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
243 return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
244 desc, field, NULL_TREE);
247 static tree
248 gfc_conv_descriptor_dimension (tree desc, tree dim)
250 tree field;
251 tree type;
252 tree tmp;
254 type = TREE_TYPE (desc);
255 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
257 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
258 gcc_assert (field != NULL_TREE
259 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
260 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
262 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
263 desc, field, NULL_TREE);
264 tmp = gfc_build_array_ref (tmp, dim, NULL);
265 return tmp;
268 static tree
269 gfc_conv_descriptor_stride (tree desc, tree dim)
271 tree tmp;
272 tree field;
274 tmp = gfc_conv_descriptor_dimension (desc, dim);
275 field = TYPE_FIELDS (TREE_TYPE (tmp));
276 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
277 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
279 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
280 tmp, field, NULL_TREE);
281 return tmp;
284 tree
285 gfc_conv_descriptor_stride_get (tree desc, tree dim)
287 tree type = TREE_TYPE (desc);
288 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
289 if (integer_zerop (dim)
290 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
291 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
292 ||GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
293 return gfc_index_one_node;
295 return gfc_conv_descriptor_stride (desc, dim);
298 void
299 gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
300 tree dim, tree value)
302 tree t = gfc_conv_descriptor_stride (desc, dim);
303 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
306 static tree
307 gfc_conv_descriptor_lbound (tree desc, tree dim)
309 tree tmp;
310 tree field;
312 tmp = gfc_conv_descriptor_dimension (desc, dim);
313 field = TYPE_FIELDS (TREE_TYPE (tmp));
314 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
315 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
317 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
318 tmp, field, NULL_TREE);
319 return tmp;
322 tree
323 gfc_conv_descriptor_lbound_get (tree desc, tree dim)
325 return gfc_conv_descriptor_lbound (desc, dim);
328 void
329 gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
330 tree dim, tree value)
332 tree t = gfc_conv_descriptor_lbound (desc, dim);
333 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
336 static tree
337 gfc_conv_descriptor_ubound (tree desc, tree dim)
339 tree tmp;
340 tree field;
342 tmp = gfc_conv_descriptor_dimension (desc, dim);
343 field = TYPE_FIELDS (TREE_TYPE (tmp));
344 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
345 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
347 tmp = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
348 tmp, field, NULL_TREE);
349 return tmp;
352 tree
353 gfc_conv_descriptor_ubound_get (tree desc, tree dim)
355 return gfc_conv_descriptor_ubound (desc, dim);
358 void
359 gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
360 tree dim, tree value)
362 tree t = gfc_conv_descriptor_ubound (desc, dim);
363 gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
366 /* Build a null array descriptor constructor. */
368 tree
369 gfc_build_null_descriptor (tree type)
371 tree field;
372 tree tmp;
374 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
375 gcc_assert (DATA_FIELD == 0);
376 field = TYPE_FIELDS (type);
378 /* Set a NULL data pointer. */
379 tmp = build_constructor_single (type, field, null_pointer_node);
380 TREE_CONSTANT (tmp) = 1;
381 /* All other fields are ignored. */
383 return tmp;
387 /* Modify a descriptor such that the lbound of a given dimension is the value
388 specified. This also updates ubound and offset accordingly. */
390 void
391 gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
392 int dim, tree new_lbound)
394 tree offs, ubound, lbound, stride;
395 tree diff, offs_diff;
397 new_lbound = fold_convert (gfc_array_index_type, new_lbound);
399 offs = gfc_conv_descriptor_offset_get (desc);
400 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
401 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
402 stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
404 /* Get difference (new - old) by which to shift stuff. */
405 diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
406 new_lbound, lbound);
408 /* Shift ubound and offset accordingly. This has to be done before
409 updating the lbound, as they depend on the lbound expression! */
410 ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
411 ubound, diff);
412 gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
413 offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
414 diff, stride);
415 offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
416 offs, offs_diff);
417 gfc_conv_descriptor_offset_set (block, desc, offs);
419 /* Finally set lbound to value we want. */
420 gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
424 /* Cleanup those #defines. */
426 #undef DATA_FIELD
427 #undef OFFSET_FIELD
428 #undef DTYPE_FIELD
429 #undef DIMENSION_FIELD
430 #undef STRIDE_SUBFIELD
431 #undef LBOUND_SUBFIELD
432 #undef UBOUND_SUBFIELD
435 /* Mark a SS chain as used. Flags specifies in which loops the SS is used.
436 flags & 1 = Main loop body.
437 flags & 2 = temp copy loop. */
439 void
440 gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
442 for (; ss != gfc_ss_terminator; ss = ss->next)
443 ss->useflags = flags;
446 static void gfc_free_ss (gfc_ss *);
449 /* Free a gfc_ss chain. */
451 void
452 gfc_free_ss_chain (gfc_ss * ss)
454 gfc_ss *next;
456 while (ss != gfc_ss_terminator)
458 gcc_assert (ss != NULL);
459 next = ss->next;
460 gfc_free_ss (ss);
461 ss = next;
466 /* Free a SS. */
468 static void
469 gfc_free_ss (gfc_ss * ss)
471 int n;
473 switch (ss->type)
475 case GFC_SS_SECTION:
476 for (n = 0; n < ss->data.info.dimen; n++)
478 if (ss->data.info.subscript[ss->data.info.dim[n]])
479 gfc_free_ss_chain (ss->data.info.subscript[ss->data.info.dim[n]]);
481 break;
483 default:
484 break;
487 gfc_free (ss);
491 /* Free all the SS associated with a loop. */
493 void
494 gfc_cleanup_loop (gfc_loopinfo * loop)
496 gfc_ss *ss;
497 gfc_ss *next;
499 ss = loop->ss;
500 while (ss != gfc_ss_terminator)
502 gcc_assert (ss != NULL);
503 next = ss->loop_chain;
504 gfc_free_ss (ss);
505 ss = next;
510 /* Associate a SS chain with a loop. */
512 void
513 gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
515 gfc_ss *ss;
517 if (head == gfc_ss_terminator)
518 return;
520 ss = head;
521 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
523 if (ss->next == gfc_ss_terminator)
524 ss->loop_chain = loop->ss;
525 else
526 ss->loop_chain = ss->next;
528 gcc_assert (ss == gfc_ss_terminator);
529 loop->ss = head;
533 /* Generate an initializer for a static pointer or allocatable array. */
535 void
536 gfc_trans_static_array_pointer (gfc_symbol * sym)
538 tree type;
540 gcc_assert (TREE_STATIC (sym->backend_decl));
541 /* Just zero the data member. */
542 type = TREE_TYPE (sym->backend_decl);
543 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
547 /* If the bounds of SE's loop have not yet been set, see if they can be
548 determined from array spec AS, which is the array spec of a called
549 function. MAPPING maps the callee's dummy arguments to the values
550 that the caller is passing. Add any initialization and finalization
551 code to SE. */
553 void
554 gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
555 gfc_se * se, gfc_array_spec * as)
557 int n, dim;
558 gfc_se tmpse;
559 tree lower;
560 tree upper;
561 tree tmp;
563 if (as && as->type == AS_EXPLICIT)
564 for (n = 0; n < se->loop->dimen; n++)
566 dim = se->ss->data.info.dim[n];
567 gcc_assert (dim < as->rank);
568 gcc_assert (se->loop->dimen == as->rank);
569 if (se->loop->to[n] == NULL_TREE)
571 /* Evaluate the lower bound. */
572 gfc_init_se (&tmpse, NULL);
573 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
574 gfc_add_block_to_block (&se->pre, &tmpse.pre);
575 gfc_add_block_to_block (&se->post, &tmpse.post);
576 lower = fold_convert (gfc_array_index_type, tmpse.expr);
578 /* ...and the upper bound. */
579 gfc_init_se (&tmpse, NULL);
580 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
581 gfc_add_block_to_block (&se->pre, &tmpse.pre);
582 gfc_add_block_to_block (&se->post, &tmpse.post);
583 upper = fold_convert (gfc_array_index_type, tmpse.expr);
585 /* Set the upper bound of the loop to UPPER - LOWER. */
586 tmp = fold_build2_loc (input_location, MINUS_EXPR,
587 gfc_array_index_type, upper, lower);
588 tmp = gfc_evaluate_now (tmp, &se->pre);
589 se->loop->to[n] = tmp;
595 /* Generate code to allocate an array temporary, or create a variable to
596 hold the data. If size is NULL, zero the descriptor so that the
597 callee will allocate the array. If DEALLOC is true, also generate code to
598 free the array afterwards.
600 If INITIAL is not NULL, it is packed using internal_pack and the result used
601 as data instead of allocating a fresh, unitialized area of memory.
603 Initialization code is added to PRE and finalization code to POST.
604 DYNAMIC is true if the caller may want to extend the array later
605 using realloc. This prevents us from putting the array on the stack. */
607 static void
608 gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
609 gfc_ss_info * info, tree size, tree nelem,
610 tree initial, bool dynamic, bool dealloc)
612 tree tmp;
613 tree desc;
614 bool onstack;
616 desc = info->descriptor;
617 info->offset = gfc_index_zero_node;
618 if (size == NULL_TREE || integer_zerop (size))
620 /* A callee allocated array. */
621 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
622 onstack = FALSE;
624 else
626 /* Allocate the temporary. */
627 onstack = !dynamic && initial == NULL_TREE
628 && gfc_can_put_var_on_stack (size);
630 if (onstack)
632 /* Make a temporary variable to hold the data. */
633 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
634 nelem, gfc_index_one_node);
635 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
636 tmp);
637 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
638 tmp);
639 tmp = gfc_create_var (tmp, "A");
640 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
641 gfc_conv_descriptor_data_set (pre, desc, tmp);
643 else
645 /* Allocate memory to hold the data or call internal_pack. */
646 if (initial == NULL_TREE)
648 tmp = gfc_call_malloc (pre, NULL, size);
649 tmp = gfc_evaluate_now (tmp, pre);
651 else
653 tree packed;
654 tree source_data;
655 tree was_packed;
656 stmtblock_t do_copying;
658 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
659 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
660 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
661 tmp = gfc_get_element_type (tmp);
662 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
663 packed = gfc_create_var (build_pointer_type (tmp), "data");
665 tmp = build_call_expr_loc (input_location,
666 gfor_fndecl_in_pack, 1, initial);
667 tmp = fold_convert (TREE_TYPE (packed), tmp);
668 gfc_add_modify (pre, packed, tmp);
670 tmp = build_fold_indirect_ref_loc (input_location,
671 initial);
672 source_data = gfc_conv_descriptor_data_get (tmp);
674 /* internal_pack may return source->data without any allocation
675 or copying if it is already packed. If that's the case, we
676 need to allocate and copy manually. */
678 gfc_start_block (&do_copying);
679 tmp = gfc_call_malloc (&do_copying, NULL, size);
680 tmp = fold_convert (TREE_TYPE (packed), tmp);
681 gfc_add_modify (&do_copying, packed, tmp);
682 tmp = gfc_build_memcpy_call (packed, source_data, size);
683 gfc_add_expr_to_block (&do_copying, tmp);
685 was_packed = fold_build2_loc (input_location, EQ_EXPR,
686 boolean_type_node, packed,
687 source_data);
688 tmp = gfc_finish_block (&do_copying);
689 tmp = build3_v (COND_EXPR, was_packed, tmp,
690 build_empty_stmt (input_location));
691 gfc_add_expr_to_block (pre, tmp);
693 tmp = fold_convert (pvoid_type_node, packed);
696 gfc_conv_descriptor_data_set (pre, desc, tmp);
699 info->data = gfc_conv_descriptor_data_get (desc);
701 /* The offset is zero because we create temporaries with a zero
702 lower bound. */
703 gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
705 if (dealloc && !onstack)
707 /* Free the temporary. */
708 tmp = gfc_conv_descriptor_data_get (desc);
709 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
710 gfc_add_expr_to_block (post, tmp);
715 /* Get the array reference dimension corresponding to the given loop dimension.
716 It is different from the true array dimension given by the dim array in
717 the case of a partial array reference
718 It is different from the loop dimension in the case of a transposed array.
721 static int
722 get_array_ref_dim (gfc_ss_info *info, int loop_dim)
724 int n, array_dim, array_ref_dim;
726 array_ref_dim = 0;
727 array_dim = info->dim[loop_dim];
729 for (n = 0; n < info->dimen; n++)
730 if (n != loop_dim && info->dim[n] < array_dim)
731 array_ref_dim++;
733 return array_ref_dim;
737 /* Generate code to create and initialize the descriptor for a temporary
738 array. This is used for both temporaries needed by the scalarizer, and
739 functions returning arrays. Adjusts the loop variables to be
740 zero-based, and calculates the loop bounds for callee allocated arrays.
741 Allocate the array unless it's callee allocated (we have a callee
742 allocated array if 'callee_alloc' is true, or if loop->to[n] is
743 NULL_TREE for any n). Also fills in the descriptor, data and offset
744 fields of info if known. Returns the size of the array, or NULL for a
745 callee allocated array.
747 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
748 gfc_trans_allocate_array_storage.
751 tree
752 gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
753 gfc_loopinfo * loop, gfc_ss_info * info,
754 tree eltype, tree initial, bool dynamic,
755 bool dealloc, bool callee_alloc, locus * where)
757 tree from[GFC_MAX_DIMENSIONS], to[GFC_MAX_DIMENSIONS];
758 tree type;
759 tree desc;
760 tree tmp;
761 tree size;
762 tree nelem;
763 tree cond;
764 tree or_expr;
765 int n, dim, tmp_dim;
767 memset (from, 0, sizeof (from));
768 memset (to, 0, sizeof (to));
770 gcc_assert (info->dimen > 0);
771 gcc_assert (loop->dimen == info->dimen);
773 if (gfc_option.warn_array_temp && where)
774 gfc_warning ("Creating array temporary at %L", where);
776 /* Set the lower bound to zero. */
777 for (n = 0; n < loop->dimen; n++)
779 dim = info->dim[n];
781 /* Callee allocated arrays may not have a known bound yet. */
782 if (loop->to[n])
783 loop->to[n] = gfc_evaluate_now (
784 fold_build2_loc (input_location, MINUS_EXPR,
785 gfc_array_index_type,
786 loop->to[n], loop->from[n]),
787 pre);
788 loop->from[n] = gfc_index_zero_node;
790 /* We are constructing the temporary's descriptor based on the loop
791 dimensions. As the dimensions may be accessed in arbitrary order
792 (think of transpose) the size taken from the n'th loop may not map
793 to the n'th dimension of the array. We need to reconstruct loop infos
794 in the right order before using it to set the descriptor
795 bounds. */
796 tmp_dim = get_array_ref_dim (info, n);
797 from[tmp_dim] = loop->from[n];
798 to[tmp_dim] = loop->to[n];
800 info->delta[dim] = gfc_index_zero_node;
801 info->start[dim] = gfc_index_zero_node;
802 info->end[dim] = gfc_index_zero_node;
803 info->stride[dim] = gfc_index_one_node;
806 /* Initialize the descriptor. */
807 type =
808 gfc_get_array_type_bounds (eltype, info->dimen, 0, from, to, 1,
809 GFC_ARRAY_UNKNOWN, true);
810 desc = gfc_create_var (type, "atmp");
811 GFC_DECL_PACKED_ARRAY (desc) = 1;
813 info->descriptor = desc;
814 size = gfc_index_one_node;
816 /* Fill in the array dtype. */
817 tmp = gfc_conv_descriptor_dtype (desc);
818 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
821 Fill in the bounds and stride. This is a packed array, so:
823 size = 1;
824 for (n = 0; n < rank; n++)
826 stride[n] = size
827 delta = ubound[n] + 1 - lbound[n];
828 size = size * delta;
830 size = size * sizeof(element);
833 or_expr = NULL_TREE;
835 /* If there is at least one null loop->to[n], it is a callee allocated
836 array. */
837 for (n = 0; n < loop->dimen; n++)
838 if (loop->to[n] == NULL_TREE)
840 size = NULL_TREE;
841 break;
844 for (n = 0; n < loop->dimen; n++)
846 dim = info->dim[n];
848 if (size == NULL_TREE)
850 /* For a callee allocated array express the loop bounds in terms
851 of the descriptor fields. */
852 tmp = fold_build2_loc (input_location,
853 MINUS_EXPR, gfc_array_index_type,
854 gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]),
855 gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]));
856 loop->to[n] = tmp;
857 continue;
860 /* Store the stride and bound components in the descriptor. */
861 gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
863 gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
864 gfc_index_zero_node);
866 gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n],
867 to[n]);
869 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
870 to[n], gfc_index_one_node);
872 /* Check whether the size for this dimension is negative. */
873 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, tmp,
874 gfc_index_zero_node);
875 cond = gfc_evaluate_now (cond, pre);
877 if (n == 0)
878 or_expr = cond;
879 else
880 or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
881 boolean_type_node, or_expr, cond);
883 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
884 size, tmp);
885 size = gfc_evaluate_now (size, pre);
888 /* Get the size of the array. */
890 if (size && !callee_alloc)
892 /* If or_expr is true, then the extent in at least one
893 dimension is zero and the size is set to zero. */
894 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
895 or_expr, gfc_index_zero_node, size);
897 nelem = size;
898 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
899 size,
900 fold_convert (gfc_array_index_type,
901 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
903 else
905 nelem = size;
906 size = NULL_TREE;
909 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
910 dynamic, dealloc);
912 if (info->dimen > loop->temp_dim)
913 loop->temp_dim = info->dimen;
915 return size;
919 /* Return the number of iterations in a loop that starts at START,
920 ends at END, and has step STEP. */
922 static tree
923 gfc_get_iteration_count (tree start, tree end, tree step)
925 tree tmp;
926 tree type;
928 type = TREE_TYPE (step);
929 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, end, start);
930 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, type, tmp, step);
931 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, tmp,
932 build_int_cst (type, 1));
933 tmp = fold_build2_loc (input_location, MAX_EXPR, type, tmp,
934 build_int_cst (type, 0));
935 return fold_convert (gfc_array_index_type, tmp);
939 /* Extend the data in array DESC by EXTRA elements. */
941 static void
942 gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
944 tree arg0, arg1;
945 tree tmp;
946 tree size;
947 tree ubound;
949 if (integer_zerop (extra))
950 return;
952 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
954 /* Add EXTRA to the upper bound. */
955 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
956 ubound, extra);
957 gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
959 /* Get the value of the current data pointer. */
960 arg0 = gfc_conv_descriptor_data_get (desc);
962 /* Calculate the new array size. */
963 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
964 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
965 ubound, gfc_index_one_node);
966 arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
967 fold_convert (size_type_node, tmp),
968 fold_convert (size_type_node, size));
970 /* Call the realloc() function. */
971 tmp = gfc_call_realloc (pblock, arg0, arg1);
972 gfc_conv_descriptor_data_set (pblock, desc, tmp);
976 /* Return true if the bounds of iterator I can only be determined
977 at run time. */
979 static inline bool
980 gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
982 return (i->start->expr_type != EXPR_CONSTANT
983 || i->end->expr_type != EXPR_CONSTANT
984 || i->step->expr_type != EXPR_CONSTANT);
988 /* Split the size of constructor element EXPR into the sum of two terms,
989 one of which can be determined at compile time and one of which must
990 be calculated at run time. Set *SIZE to the former and return true
991 if the latter might be nonzero. */
993 static bool
994 gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
996 if (expr->expr_type == EXPR_ARRAY)
997 return gfc_get_array_constructor_size (size, expr->value.constructor);
998 else if (expr->rank > 0)
1000 /* Calculate everything at run time. */
1001 mpz_set_ui (*size, 0);
1002 return true;
1004 else
1006 /* A single element. */
1007 mpz_set_ui (*size, 1);
1008 return false;
1013 /* Like gfc_get_array_constructor_element_size, but applied to the whole
1014 of array constructor C. */
1016 static bool
1017 gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
1019 gfc_constructor *c;
1020 gfc_iterator *i;
1021 mpz_t val;
1022 mpz_t len;
1023 bool dynamic;
1025 mpz_set_ui (*size, 0);
1026 mpz_init (len);
1027 mpz_init (val);
1029 dynamic = false;
1030 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1032 i = c->iterator;
1033 if (i && gfc_iterator_has_dynamic_bounds (i))
1034 dynamic = true;
1035 else
1037 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
1038 if (i)
1040 /* Multiply the static part of the element size by the
1041 number of iterations. */
1042 mpz_sub (val, i->end->value.integer, i->start->value.integer);
1043 mpz_fdiv_q (val, val, i->step->value.integer);
1044 mpz_add_ui (val, val, 1);
1045 if (mpz_sgn (val) > 0)
1046 mpz_mul (len, len, val);
1047 else
1048 mpz_set_ui (len, 0);
1050 mpz_add (*size, *size, len);
1053 mpz_clear (len);
1054 mpz_clear (val);
1055 return dynamic;
1059 /* Make sure offset is a variable. */
1061 static void
1062 gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1063 tree * offsetvar)
1065 /* We should have already created the offset variable. We cannot
1066 create it here because we may be in an inner scope. */
1067 gcc_assert (*offsetvar != NULL_TREE);
1068 gfc_add_modify (pblock, *offsetvar, *poffset);
1069 *poffset = *offsetvar;
1070 TREE_USED (*offsetvar) = 1;
1074 /* Variables needed for bounds-checking. */
1075 static bool first_len;
1076 static tree first_len_val;
1077 static bool typespec_chararray_ctor;
1079 static void
1080 gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
1081 tree offset, gfc_se * se, gfc_expr * expr)
1083 tree tmp;
1085 gfc_conv_expr (se, expr);
1087 /* Store the value. */
1088 tmp = build_fold_indirect_ref_loc (input_location,
1089 gfc_conv_descriptor_data_get (desc));
1090 tmp = gfc_build_array_ref (tmp, offset, NULL);
1092 if (expr->ts.type == BT_CHARACTER)
1094 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1095 tree esize;
1097 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1098 esize = fold_convert (gfc_charlen_type_node, esize);
1099 esize = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1100 gfc_charlen_type_node, esize,
1101 build_int_cst (gfc_charlen_type_node,
1102 gfc_character_kinds[i].bit_size / 8));
1104 gfc_conv_string_parameter (se);
1105 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1107 /* The temporary is an array of pointers. */
1108 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1109 gfc_add_modify (&se->pre, tmp, se->expr);
1111 else
1113 /* The temporary is an array of string values. */
1114 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
1115 /* We know the temporary and the value will be the same length,
1116 so can use memcpy. */
1117 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1118 se->string_length, se->expr, expr->ts.kind);
1120 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
1122 if (first_len)
1124 gfc_add_modify (&se->pre, first_len_val,
1125 se->string_length);
1126 first_len = false;
1128 else
1130 /* Verify that all constructor elements are of the same
1131 length. */
1132 tree cond = fold_build2_loc (input_location, NE_EXPR,
1133 boolean_type_node, first_len_val,
1134 se->string_length);
1135 gfc_trans_runtime_check
1136 (true, false, cond, &se->pre, &expr->where,
1137 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1138 fold_convert (long_integer_type_node, first_len_val),
1139 fold_convert (long_integer_type_node, se->string_length));
1143 else
1145 /* TODO: Should the frontend already have done this conversion? */
1146 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
1147 gfc_add_modify (&se->pre, tmp, se->expr);
1150 gfc_add_block_to_block (pblock, &se->pre);
1151 gfc_add_block_to_block (pblock, &se->post);
1155 /* Add the contents of an array to the constructor. DYNAMIC is as for
1156 gfc_trans_array_constructor_value. */
1158 static void
1159 gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1160 tree type ATTRIBUTE_UNUSED,
1161 tree desc, gfc_expr * expr,
1162 tree * poffset, tree * offsetvar,
1163 bool dynamic)
1165 gfc_se se;
1166 gfc_ss *ss;
1167 gfc_loopinfo loop;
1168 stmtblock_t body;
1169 tree tmp;
1170 tree size;
1171 int n;
1173 /* We need this to be a variable so we can increment it. */
1174 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1176 gfc_init_se (&se, NULL);
1178 /* Walk the array expression. */
1179 ss = gfc_walk_expr (expr);
1180 gcc_assert (ss != gfc_ss_terminator);
1182 /* Initialize the scalarizer. */
1183 gfc_init_loopinfo (&loop);
1184 gfc_add_ss_to_loop (&loop, ss);
1186 /* Initialize the loop. */
1187 gfc_conv_ss_startstride (&loop);
1188 gfc_conv_loop_setup (&loop, &expr->where);
1190 /* Make sure the constructed array has room for the new data. */
1191 if (dynamic)
1193 /* Set SIZE to the total number of elements in the subarray. */
1194 size = gfc_index_one_node;
1195 for (n = 0; n < loop.dimen; n++)
1197 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1198 gfc_index_one_node);
1199 size = fold_build2_loc (input_location, MULT_EXPR,
1200 gfc_array_index_type, size, tmp);
1203 /* Grow the constructed array by SIZE elements. */
1204 gfc_grow_array (&loop.pre, desc, size);
1207 /* Make the loop body. */
1208 gfc_mark_ss_chain_used (ss, 1);
1209 gfc_start_scalarized_body (&loop, &body);
1210 gfc_copy_loopinfo_to_se (&se, &loop);
1211 se.ss = ss;
1213 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
1214 gcc_assert (se.ss == gfc_ss_terminator);
1216 /* Increment the offset. */
1217 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1218 *poffset, gfc_index_one_node);
1219 gfc_add_modify (&body, *poffset, tmp);
1221 /* Finish the loop. */
1222 gfc_trans_scalarizing_loops (&loop, &body);
1223 gfc_add_block_to_block (&loop.pre, &loop.post);
1224 tmp = gfc_finish_block (&loop.pre);
1225 gfc_add_expr_to_block (pblock, tmp);
1227 gfc_cleanup_loop (&loop);
1231 /* Assign the values to the elements of an array constructor. DYNAMIC
1232 is true if descriptor DESC only contains enough data for the static
1233 size calculated by gfc_get_array_constructor_size. When true, memory
1234 for the dynamic parts must be allocated using realloc. */
1236 static void
1237 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
1238 tree desc, gfc_constructor_base base,
1239 tree * poffset, tree * offsetvar,
1240 bool dynamic)
1242 tree tmp;
1243 stmtblock_t body;
1244 gfc_se se;
1245 mpz_t size;
1246 gfc_constructor *c;
1248 tree shadow_loopvar = NULL_TREE;
1249 gfc_saved_var saved_loopvar;
1251 mpz_init (size);
1252 for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
1254 /* If this is an iterator or an array, the offset must be a variable. */
1255 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1256 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1258 /* Shadowing the iterator avoids changing its value and saves us from
1259 keeping track of it. Further, it makes sure that there's always a
1260 backend-decl for the symbol, even if there wasn't one before,
1261 e.g. in the case of an iterator that appears in a specification
1262 expression in an interface mapping. */
1263 if (c->iterator)
1265 gfc_symbol *sym = c->iterator->var->symtree->n.sym;
1266 tree type = gfc_typenode_for_spec (&sym->ts);
1268 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1269 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1272 gfc_start_block (&body);
1274 if (c->expr->expr_type == EXPR_ARRAY)
1276 /* Array constructors can be nested. */
1277 gfc_trans_array_constructor_value (&body, type, desc,
1278 c->expr->value.constructor,
1279 poffset, offsetvar, dynamic);
1281 else if (c->expr->rank > 0)
1283 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1284 poffset, offsetvar, dynamic);
1286 else
1288 /* This code really upsets the gimplifier so don't bother for now. */
1289 gfc_constructor *p;
1290 HOST_WIDE_INT n;
1291 HOST_WIDE_INT size;
1293 p = c;
1294 n = 0;
1295 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1297 p = gfc_constructor_next (p);
1298 n++;
1300 if (n < 4)
1302 /* Scalar values. */
1303 gfc_init_se (&se, NULL);
1304 gfc_trans_array_ctor_element (&body, desc, *poffset,
1305 &se, c->expr);
1307 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1308 gfc_array_index_type,
1309 *poffset, gfc_index_one_node);
1311 else
1313 /* Collect multiple scalar constants into a constructor. */
1314 VEC(constructor_elt,gc) *v = NULL;
1315 tree init;
1316 tree bound;
1317 tree tmptype;
1318 HOST_WIDE_INT idx = 0;
1320 p = c;
1321 /* Count the number of consecutive scalar constants. */
1322 while (p && !(p->iterator
1323 || p->expr->expr_type != EXPR_CONSTANT))
1325 gfc_init_se (&se, NULL);
1326 gfc_conv_constant (&se, p->expr);
1328 if (c->expr->ts.type != BT_CHARACTER)
1329 se.expr = fold_convert (type, se.expr);
1330 /* For constant character array constructors we build
1331 an array of pointers. */
1332 else if (POINTER_TYPE_P (type))
1333 se.expr = gfc_build_addr_expr
1334 (gfc_get_pchar_type (p->expr->ts.kind),
1335 se.expr);
1337 CONSTRUCTOR_APPEND_ELT (v,
1338 build_int_cst (gfc_array_index_type,
1339 idx++),
1340 se.expr);
1341 c = p;
1342 p = gfc_constructor_next (p);
1345 bound = build_int_cst (NULL_TREE, n - 1);
1346 /* Create an array type to hold them. */
1347 tmptype = build_range_type (gfc_array_index_type,
1348 gfc_index_zero_node, bound);
1349 tmptype = build_array_type (type, tmptype);
1351 init = build_constructor (tmptype, v);
1352 TREE_CONSTANT (init) = 1;
1353 TREE_STATIC (init) = 1;
1354 /* Create a static variable to hold the data. */
1355 tmp = gfc_create_var (tmptype, "data");
1356 TREE_STATIC (tmp) = 1;
1357 TREE_CONSTANT (tmp) = 1;
1358 TREE_READONLY (tmp) = 1;
1359 DECL_INITIAL (tmp) = init;
1360 init = tmp;
1362 /* Use BUILTIN_MEMCPY to assign the values. */
1363 tmp = gfc_conv_descriptor_data_get (desc);
1364 tmp = build_fold_indirect_ref_loc (input_location,
1365 tmp);
1366 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
1367 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1368 init = gfc_build_addr_expr (NULL_TREE, init);
1370 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
1371 bound = build_int_cst (NULL_TREE, n * size);
1372 tmp = build_call_expr_loc (input_location,
1373 built_in_decls[BUILT_IN_MEMCPY], 3,
1374 tmp, init, bound);
1375 gfc_add_expr_to_block (&body, tmp);
1377 *poffset = fold_build2_loc (input_location, PLUS_EXPR,
1378 gfc_array_index_type, *poffset,
1379 build_int_cst (gfc_array_index_type, n));
1381 if (!INTEGER_CST_P (*poffset))
1383 gfc_add_modify (&body, *offsetvar, *poffset);
1384 *poffset = *offsetvar;
1388 /* The frontend should already have done any expansions
1389 at compile-time. */
1390 if (!c->iterator)
1392 /* Pass the code as is. */
1393 tmp = gfc_finish_block (&body);
1394 gfc_add_expr_to_block (pblock, tmp);
1396 else
1398 /* Build the implied do-loop. */
1399 stmtblock_t implied_do_block;
1400 tree cond;
1401 tree end;
1402 tree step;
1403 tree exit_label;
1404 tree loopbody;
1405 tree tmp2;
1407 loopbody = gfc_finish_block (&body);
1409 /* Create a new block that holds the implied-do loop. A temporary
1410 loop-variable is used. */
1411 gfc_start_block(&implied_do_block);
1413 /* Initialize the loop. */
1414 gfc_init_se (&se, NULL);
1415 gfc_conv_expr_val (&se, c->iterator->start);
1416 gfc_add_block_to_block (&implied_do_block, &se.pre);
1417 gfc_add_modify (&implied_do_block, shadow_loopvar, se.expr);
1419 gfc_init_se (&se, NULL);
1420 gfc_conv_expr_val (&se, c->iterator->end);
1421 gfc_add_block_to_block (&implied_do_block, &se.pre);
1422 end = gfc_evaluate_now (se.expr, &implied_do_block);
1424 gfc_init_se (&se, NULL);
1425 gfc_conv_expr_val (&se, c->iterator->step);
1426 gfc_add_block_to_block (&implied_do_block, &se.pre);
1427 step = gfc_evaluate_now (se.expr, &implied_do_block);
1429 /* If this array expands dynamically, and the number of iterations
1430 is not constant, we won't have allocated space for the static
1431 part of C->EXPR's size. Do that now. */
1432 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1434 /* Get the number of iterations. */
1435 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
1437 /* Get the static part of C->EXPR's size. */
1438 gfc_get_array_constructor_element_size (&size, c->expr);
1439 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1441 /* Grow the array by TMP * TMP2 elements. */
1442 tmp = fold_build2_loc (input_location, MULT_EXPR,
1443 gfc_array_index_type, tmp, tmp2);
1444 gfc_grow_array (&implied_do_block, desc, tmp);
1447 /* Generate the loop body. */
1448 exit_label = gfc_build_label_decl (NULL_TREE);
1449 gfc_start_block (&body);
1451 /* Generate the exit condition. Depending on the sign of
1452 the step variable we have to generate the correct
1453 comparison. */
1454 tmp = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1455 step, build_int_cst (TREE_TYPE (step), 0));
1456 cond = fold_build3_loc (input_location, COND_EXPR,
1457 boolean_type_node, tmp,
1458 fold_build2_loc (input_location, GT_EXPR,
1459 boolean_type_node, shadow_loopvar, end),
1460 fold_build2_loc (input_location, LT_EXPR,
1461 boolean_type_node, shadow_loopvar, end));
1462 tmp = build1_v (GOTO_EXPR, exit_label);
1463 TREE_USED (exit_label) = 1;
1464 tmp = build3_v (COND_EXPR, cond, tmp,
1465 build_empty_stmt (input_location));
1466 gfc_add_expr_to_block (&body, tmp);
1468 /* The main loop body. */
1469 gfc_add_expr_to_block (&body, loopbody);
1471 /* Increase loop variable by step. */
1472 tmp = fold_build2_loc (input_location, PLUS_EXPR,
1473 TREE_TYPE (shadow_loopvar), shadow_loopvar,
1474 step);
1475 gfc_add_modify (&body, shadow_loopvar, tmp);
1477 /* Finish the loop. */
1478 tmp = gfc_finish_block (&body);
1479 tmp = build1_v (LOOP_EXPR, tmp);
1480 gfc_add_expr_to_block (&implied_do_block, tmp);
1482 /* Add the exit label. */
1483 tmp = build1_v (LABEL_EXPR, exit_label);
1484 gfc_add_expr_to_block (&implied_do_block, tmp);
1486 /* Finishe the implied-do loop. */
1487 tmp = gfc_finish_block(&implied_do_block);
1488 gfc_add_expr_to_block(pblock, tmp);
1490 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
1493 mpz_clear (size);
1497 /* Figure out the string length of a variable reference expression.
1498 Used by get_array_ctor_strlen. */
1500 static void
1501 get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1503 gfc_ref *ref;
1504 gfc_typespec *ts;
1505 mpz_t char_len;
1507 /* Don't bother if we already know the length is a constant. */
1508 if (*len && INTEGER_CST_P (*len))
1509 return;
1511 ts = &expr->symtree->n.sym->ts;
1512 for (ref = expr->ref; ref; ref = ref->next)
1514 switch (ref->type)
1516 case REF_ARRAY:
1517 /* Array references don't change the string length. */
1518 break;
1520 case REF_COMPONENT:
1521 /* Use the length of the component. */
1522 ts = &ref->u.c.component->ts;
1523 break;
1525 case REF_SUBSTRING:
1526 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
1527 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1528 break;
1529 mpz_init_set_ui (char_len, 1);
1530 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1531 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
1532 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1533 *len = convert (gfc_charlen_type_node, *len);
1534 mpz_clear (char_len);
1535 return;
1537 default:
1538 /* TODO: Substrings are tricky because we can't evaluate the
1539 expression more than once. For now we just give up, and hope
1540 we can figure it out elsewhere. */
1541 return;
1545 *len = ts->u.cl->backend_decl;
1549 /* A catch-all to obtain the string length for anything that is not a
1550 constant, array or variable. */
1551 static void
1552 get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1554 gfc_se se;
1555 gfc_ss *ss;
1557 /* Don't bother if we already know the length is a constant. */
1558 if (*len && INTEGER_CST_P (*len))
1559 return;
1561 if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
1562 && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
1564 /* This is easy. */
1565 gfc_conv_const_charlen (e->ts.u.cl);
1566 *len = e->ts.u.cl->backend_decl;
1568 else
1570 /* Otherwise, be brutal even if inefficient. */
1571 ss = gfc_walk_expr (e);
1572 gfc_init_se (&se, NULL);
1574 /* No function call, in case of side effects. */
1575 se.no_function_call = 1;
1576 if (ss == gfc_ss_terminator)
1577 gfc_conv_expr (&se, e);
1578 else
1579 gfc_conv_expr_descriptor (&se, e, ss);
1581 /* Fix the value. */
1582 *len = gfc_evaluate_now (se.string_length, &se.pre);
1584 gfc_add_block_to_block (block, &se.pre);
1585 gfc_add_block_to_block (block, &se.post);
1587 e->ts.u.cl->backend_decl = *len;
1592 /* Figure out the string length of a character array constructor.
1593 If len is NULL, don't calculate the length; this happens for recursive calls
1594 when a sub-array-constructor is an element but not at the first position,
1595 so when we're not interested in the length.
1596 Returns TRUE if all elements are character constants. */
1598 bool
1599 get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
1601 gfc_constructor *c;
1602 bool is_const;
1604 is_const = TRUE;
1606 if (gfc_constructor_first (base) == NULL)
1608 if (len)
1609 *len = build_int_cstu (gfc_charlen_type_node, 0);
1610 return is_const;
1613 /* Loop over all constructor elements to find out is_const, but in len we
1614 want to store the length of the first, not the last, element. We can
1615 of course exit the loop as soon as is_const is found to be false. */
1616 for (c = gfc_constructor_first (base);
1617 c && is_const; c = gfc_constructor_next (c))
1619 switch (c->expr->expr_type)
1621 case EXPR_CONSTANT:
1622 if (len && !(*len && INTEGER_CST_P (*len)))
1623 *len = build_int_cstu (gfc_charlen_type_node,
1624 c->expr->value.character.length);
1625 break;
1627 case EXPR_ARRAY:
1628 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
1629 is_const = false;
1630 break;
1632 case EXPR_VARIABLE:
1633 is_const = false;
1634 if (len)
1635 get_array_ctor_var_strlen (c->expr, len);
1636 break;
1638 default:
1639 is_const = false;
1640 if (len)
1641 get_array_ctor_all_strlen (block, c->expr, len);
1642 break;
1645 /* After the first iteration, we don't want the length modified. */
1646 len = NULL;
1649 return is_const;
1652 /* Check whether the array constructor C consists entirely of constant
1653 elements, and if so returns the number of those elements, otherwise
1654 return zero. Note, an empty or NULL array constructor returns zero. */
1656 unsigned HOST_WIDE_INT
1657 gfc_constant_array_constructor_p (gfc_constructor_base base)
1659 unsigned HOST_WIDE_INT nelem = 0;
1661 gfc_constructor *c = gfc_constructor_first (base);
1662 while (c)
1664 if (c->iterator
1665 || c->expr->rank > 0
1666 || c->expr->expr_type != EXPR_CONSTANT)
1667 return 0;
1668 c = gfc_constructor_next (c);
1669 nelem++;
1671 return nelem;
1675 /* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1676 and the tree type of it's elements, TYPE, return a static constant
1677 variable that is compile-time initialized. */
1679 tree
1680 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1682 tree tmptype, init, tmp;
1683 HOST_WIDE_INT nelem;
1684 gfc_constructor *c;
1685 gfc_array_spec as;
1686 gfc_se se;
1687 int i;
1688 VEC(constructor_elt,gc) *v = NULL;
1690 /* First traverse the constructor list, converting the constants
1691 to tree to build an initializer. */
1692 nelem = 0;
1693 c = gfc_constructor_first (expr->value.constructor);
1694 while (c)
1696 gfc_init_se (&se, NULL);
1697 gfc_conv_constant (&se, c->expr);
1698 if (c->expr->ts.type != BT_CHARACTER)
1699 se.expr = fold_convert (type, se.expr);
1700 else if (POINTER_TYPE_P (type))
1701 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
1702 se.expr);
1703 CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
1704 se.expr);
1705 c = gfc_constructor_next (c);
1706 nelem++;
1709 /* Next determine the tree type for the array. We use the gfortran
1710 front-end's gfc_get_nodesc_array_type in order to create a suitable
1711 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1713 memset (&as, 0, sizeof (gfc_array_spec));
1715 as.rank = expr->rank;
1716 as.type = AS_EXPLICIT;
1717 if (!expr->shape)
1719 as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1720 as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
1721 NULL, nelem - 1);
1723 else
1724 for (i = 0; i < expr->rank; i++)
1726 int tmp = (int) mpz_get_si (expr->shape[i]);
1727 as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1728 as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
1729 NULL, tmp - 1);
1732 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
1734 /* as is not needed anymore. */
1735 for (i = 0; i < as.rank + as.corank; i++)
1737 gfc_free_expr (as.lower[i]);
1738 gfc_free_expr (as.upper[i]);
1741 init = build_constructor (tmptype, v);
1743 TREE_CONSTANT (init) = 1;
1744 TREE_STATIC (init) = 1;
1746 tmp = gfc_create_var (tmptype, "A");
1747 TREE_STATIC (tmp) = 1;
1748 TREE_CONSTANT (tmp) = 1;
1749 TREE_READONLY (tmp) = 1;
1750 DECL_INITIAL (tmp) = init;
1752 return tmp;
1756 /* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1757 This mostly initializes the scalarizer state info structure with the
1758 appropriate values to directly use the array created by the function
1759 gfc_build_constant_array_constructor. */
1761 static void
1762 gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
1763 gfc_ss * ss, tree type)
1765 gfc_ss_info *info;
1766 tree tmp;
1767 int i;
1769 tmp = gfc_build_constant_array_constructor (ss->expr, type);
1771 info = &ss->data.info;
1773 info->descriptor = tmp;
1774 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
1775 info->offset = gfc_index_zero_node;
1777 for (i = 0; i < info->dimen; i++)
1779 info->delta[i] = gfc_index_zero_node;
1780 info->start[i] = gfc_index_zero_node;
1781 info->end[i] = gfc_index_zero_node;
1782 info->stride[i] = gfc_index_one_node;
1783 info->dim[i] = i;
1786 if (info->dimen > loop->temp_dim)
1787 loop->temp_dim = info->dimen;
1790 /* Helper routine of gfc_trans_array_constructor to determine if the
1791 bounds of the loop specified by LOOP are constant and simple enough
1792 to use with gfc_trans_constant_array_constructor. Returns the
1793 iteration count of the loop if suitable, and NULL_TREE otherwise. */
1795 static tree
1796 constant_array_constructor_loop_size (gfc_loopinfo * loop)
1798 tree size = gfc_index_one_node;
1799 tree tmp;
1800 int i;
1802 for (i = 0; i < loop->dimen; i++)
1804 /* If the bounds aren't constant, return NULL_TREE. */
1805 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1806 return NULL_TREE;
1807 if (!integer_zerop (loop->from[i]))
1809 /* Only allow nonzero "from" in one-dimensional arrays. */
1810 if (loop->dimen != 1)
1811 return NULL_TREE;
1812 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1813 gfc_array_index_type,
1814 loop->to[i], loop->from[i]);
1816 else
1817 tmp = loop->to[i];
1818 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1819 tmp, gfc_index_one_node);
1820 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1821 size, tmp);
1824 return size;
1828 /* Array constructors are handled by constructing a temporary, then using that
1829 within the scalarization loop. This is not optimal, but seems by far the
1830 simplest method. */
1832 static void
1833 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
1835 gfc_constructor_base c;
1836 tree offset;
1837 tree offsetvar;
1838 tree desc;
1839 tree type;
1840 tree tmp;
1841 bool dynamic;
1842 bool old_first_len, old_typespec_chararray_ctor;
1843 tree old_first_len_val;
1845 /* Save the old values for nested checking. */
1846 old_first_len = first_len;
1847 old_first_len_val = first_len_val;
1848 old_typespec_chararray_ctor = typespec_chararray_ctor;
1850 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
1851 typespec was given for the array constructor. */
1852 typespec_chararray_ctor = (ss->expr->ts.u.cl
1853 && ss->expr->ts.u.cl->length_from_typespec);
1855 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1856 && ss->expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
1858 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1859 first_len = true;
1862 ss->data.info.dimen = loop->dimen;
1864 c = ss->expr->value.constructor;
1865 if (ss->expr->ts.type == BT_CHARACTER)
1867 bool const_string;
1869 /* get_array_ctor_strlen walks the elements of the constructor, if a
1870 typespec was given, we already know the string length and want the one
1871 specified there. */
1872 if (typespec_chararray_ctor && ss->expr->ts.u.cl->length
1873 && ss->expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
1875 gfc_se length_se;
1877 const_string = false;
1878 gfc_init_se (&length_se, NULL);
1879 gfc_conv_expr_type (&length_se, ss->expr->ts.u.cl->length,
1880 gfc_charlen_type_node);
1881 ss->string_length = length_se.expr;
1882 gfc_add_block_to_block (&loop->pre, &length_se.pre);
1883 gfc_add_block_to_block (&loop->post, &length_se.post);
1885 else
1886 const_string = get_array_ctor_strlen (&loop->pre, c,
1887 &ss->string_length);
1889 /* Complex character array constructors should have been taken care of
1890 and not end up here. */
1891 gcc_assert (ss->string_length);
1893 ss->expr->ts.u.cl->backend_decl = ss->string_length;
1895 type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1896 if (const_string)
1897 type = build_pointer_type (type);
1899 else
1900 type = gfc_typenode_for_spec (&ss->expr->ts);
1902 /* See if the constructor determines the loop bounds. */
1903 dynamic = false;
1905 if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
1907 /* We have a multidimensional parameter. */
1908 int n;
1909 for (n = 0; n < ss->expr->rank; n++)
1911 loop->from[n] = gfc_index_zero_node;
1912 loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
1913 gfc_index_integer_kind);
1914 loop->to[n] = fold_build2_loc (input_location, MINUS_EXPR,
1915 gfc_array_index_type,
1916 loop->to[n], gfc_index_one_node);
1920 if (loop->to[0] == NULL_TREE)
1922 mpz_t size;
1924 /* We should have a 1-dimensional, zero-based loop. */
1925 gcc_assert (loop->dimen == 1);
1926 gcc_assert (integer_zerop (loop->from[0]));
1928 /* Split the constructor size into a static part and a dynamic part.
1929 Allocate the static size up-front and record whether the dynamic
1930 size might be nonzero. */
1931 mpz_init (size);
1932 dynamic = gfc_get_array_constructor_size (&size, c);
1933 mpz_sub_ui (size, size, 1);
1934 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1935 mpz_clear (size);
1938 /* Special case constant array constructors. */
1939 if (!dynamic)
1941 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
1942 if (nelem > 0)
1944 tree size = constant_array_constructor_loop_size (loop);
1945 if (size && compare_tree_int (size, nelem) == 0)
1947 gfc_trans_constant_array_constructor (loop, ss, type);
1948 goto finish;
1953 if (TREE_CODE (loop->to[0]) == VAR_DECL)
1954 dynamic = true;
1956 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
1957 type, NULL_TREE, dynamic, true, false, where);
1959 desc = ss->data.info.descriptor;
1960 offset = gfc_index_zero_node;
1961 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1962 TREE_NO_WARNING (offsetvar) = 1;
1963 TREE_USED (offsetvar) = 0;
1964 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
1965 &offset, &offsetvar, dynamic);
1967 /* If the array grows dynamically, the upper bound of the loop variable
1968 is determined by the array's final upper bound. */
1969 if (dynamic)
1971 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1972 gfc_array_index_type,
1973 offsetvar, gfc_index_one_node);
1974 tmp = gfc_evaluate_now (tmp, &loop->pre);
1975 gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
1976 if (loop->to[0] && TREE_CODE (loop->to[0]) == VAR_DECL)
1977 gfc_add_modify (&loop->pre, loop->to[0], tmp);
1978 else
1979 loop->to[0] = tmp;
1982 if (TREE_USED (offsetvar))
1983 pushdecl (offsetvar);
1984 else
1985 gcc_assert (INTEGER_CST_P (offset));
1987 #if 0
1988 /* Disable bound checking for now because it's probably broken. */
1989 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1991 gcc_unreachable ();
1993 #endif
1995 finish:
1996 /* Restore old values of globals. */
1997 first_len = old_first_len;
1998 first_len_val = old_first_len_val;
1999 typespec_chararray_ctor = old_typespec_chararray_ctor;
2003 /* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
2004 called after evaluating all of INFO's vector dimensions. Go through
2005 each such vector dimension and see if we can now fill in any missing
2006 loop bounds. */
2008 static void
2009 gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
2011 gfc_se se;
2012 tree tmp;
2013 tree desc;
2014 tree zero;
2015 int n;
2016 int dim;
2018 for (n = 0; n < loop->dimen; n++)
2020 dim = info->dim[n];
2021 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
2022 && loop->to[n] == NULL)
2024 /* Loop variable N indexes vector dimension DIM, and we don't
2025 yet know the upper bound of loop variable N. Set it to the
2026 difference between the vector's upper and lower bounds. */
2027 gcc_assert (loop->from[n] == gfc_index_zero_node);
2028 gcc_assert (info->subscript[dim]
2029 && info->subscript[dim]->type == GFC_SS_VECTOR);
2031 gfc_init_se (&se, NULL);
2032 desc = info->subscript[dim]->data.info.descriptor;
2033 zero = gfc_rank_cst[0];
2034 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2035 gfc_array_index_type,
2036 gfc_conv_descriptor_ubound_get (desc, zero),
2037 gfc_conv_descriptor_lbound_get (desc, zero));
2038 tmp = gfc_evaluate_now (tmp, &loop->pre);
2039 loop->to[n] = tmp;
2045 /* Add the pre and post chains for all the scalar expressions in a SS chain
2046 to loop. This is called after the loop parameters have been calculated,
2047 but before the actual scalarizing loops. */
2049 static void
2050 gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
2051 locus * where)
2053 gfc_se se;
2054 int n;
2056 /* TODO: This can generate bad code if there are ordering dependencies,
2057 e.g., a callee allocated function and an unknown size constructor. */
2058 gcc_assert (ss != NULL);
2060 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
2062 gcc_assert (ss);
2064 switch (ss->type)
2066 case GFC_SS_SCALAR:
2067 /* Scalar expression. Evaluate this now. This includes elemental
2068 dimension indices, but not array section bounds. */
2069 gfc_init_se (&se, NULL);
2070 gfc_conv_expr (&se, ss->expr);
2071 gfc_add_block_to_block (&loop->pre, &se.pre);
2073 if (ss->expr->ts.type != BT_CHARACTER)
2075 /* Move the evaluation of scalar expressions outside the
2076 scalarization loop, except for WHERE assignments. */
2077 if (subscript)
2078 se.expr = convert(gfc_array_index_type, se.expr);
2079 if (!ss->where)
2080 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
2081 gfc_add_block_to_block (&loop->pre, &se.post);
2083 else
2084 gfc_add_block_to_block (&loop->post, &se.post);
2086 ss->data.scalar.expr = se.expr;
2087 ss->string_length = se.string_length;
2088 break;
2090 case GFC_SS_REFERENCE:
2091 /* Scalar argument to elemental procedure. Evaluate this
2092 now. */
2093 gfc_init_se (&se, NULL);
2094 gfc_conv_expr (&se, ss->expr);
2095 gfc_add_block_to_block (&loop->pre, &se.pre);
2096 gfc_add_block_to_block (&loop->post, &se.post);
2098 ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
2099 ss->string_length = se.string_length;
2100 break;
2102 case GFC_SS_SECTION:
2103 /* Add the expressions for scalar and vector subscripts. */
2104 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2105 if (ss->data.info.subscript[n])
2106 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true,
2107 where);
2109 gfc_set_vector_loop_bounds (loop, &ss->data.info);
2110 break;
2112 case GFC_SS_VECTOR:
2113 /* Get the vector's descriptor and store it in SS. */
2114 gfc_init_se (&se, NULL);
2115 gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
2116 gfc_add_block_to_block (&loop->pre, &se.pre);
2117 gfc_add_block_to_block (&loop->post, &se.post);
2118 ss->data.info.descriptor = se.expr;
2119 break;
2121 case GFC_SS_INTRINSIC:
2122 gfc_add_intrinsic_ss_code (loop, ss);
2123 break;
2125 case GFC_SS_FUNCTION:
2126 /* Array function return value. We call the function and save its
2127 result in a temporary for use inside the loop. */
2128 gfc_init_se (&se, NULL);
2129 se.loop = loop;
2130 se.ss = ss;
2131 gfc_conv_expr (&se, ss->expr);
2132 gfc_add_block_to_block (&loop->pre, &se.pre);
2133 gfc_add_block_to_block (&loop->post, &se.post);
2134 ss->string_length = se.string_length;
2135 break;
2137 case GFC_SS_CONSTRUCTOR:
2138 if (ss->expr->ts.type == BT_CHARACTER
2139 && ss->string_length == NULL
2140 && ss->expr->ts.u.cl
2141 && ss->expr->ts.u.cl->length)
2143 gfc_init_se (&se, NULL);
2144 gfc_conv_expr_type (&se, ss->expr->ts.u.cl->length,
2145 gfc_charlen_type_node);
2146 ss->string_length = se.expr;
2147 gfc_add_block_to_block (&loop->pre, &se.pre);
2148 gfc_add_block_to_block (&loop->post, &se.post);
2150 gfc_trans_array_constructor (loop, ss, where);
2151 break;
2153 case GFC_SS_TEMP:
2154 case GFC_SS_COMPONENT:
2155 /* Do nothing. These are handled elsewhere. */
2156 break;
2158 default:
2159 gcc_unreachable ();
2165 /* Translate expressions for the descriptor and data pointer of a SS. */
2166 /*GCC ARRAYS*/
2168 static void
2169 gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2171 gfc_se se;
2172 tree tmp;
2174 /* Get the descriptor for the array to be scalarized. */
2175 gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
2176 gfc_init_se (&se, NULL);
2177 se.descriptor_only = 1;
2178 gfc_conv_expr_lhs (&se, ss->expr);
2179 gfc_add_block_to_block (block, &se.pre);
2180 ss->data.info.descriptor = se.expr;
2181 ss->string_length = se.string_length;
2183 if (base)
2185 /* Also the data pointer. */
2186 tmp = gfc_conv_array_data (se.expr);
2187 /* If this is a variable or address of a variable we use it directly.
2188 Otherwise we must evaluate it now to avoid breaking dependency
2189 analysis by pulling the expressions for elemental array indices
2190 inside the loop. */
2191 if (!(DECL_P (tmp)
2192 || (TREE_CODE (tmp) == ADDR_EXPR
2193 && DECL_P (TREE_OPERAND (tmp, 0)))))
2194 tmp = gfc_evaluate_now (tmp, block);
2195 ss->data.info.data = tmp;
2197 tmp = gfc_conv_array_offset (se.expr);
2198 ss->data.info.offset = gfc_evaluate_now (tmp, block);
2200 /* Make absolutely sure that the saved_offset is indeed saved
2201 so that the variable is still accessible after the loops
2202 are translated. */
2203 ss->data.info.saved_offset = ss->data.info.offset;
2208 /* Initialize a gfc_loopinfo structure. */
2210 void
2211 gfc_init_loopinfo (gfc_loopinfo * loop)
2213 int n;
2215 memset (loop, 0, sizeof (gfc_loopinfo));
2216 gfc_init_block (&loop->pre);
2217 gfc_init_block (&loop->post);
2219 /* Initially scalarize in order and default to no loop reversal. */
2220 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2222 loop->order[n] = n;
2223 loop->reverse[n] = GFC_CANNOT_REVERSE;
2226 loop->ss = gfc_ss_terminator;
2230 /* Copies the loop variable info to a gfc_se structure. Does not copy the SS
2231 chain. */
2233 void
2234 gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2236 se->loop = loop;
2240 /* Return an expression for the data pointer of an array. */
2242 tree
2243 gfc_conv_array_data (tree descriptor)
2245 tree type;
2247 type = TREE_TYPE (descriptor);
2248 if (GFC_ARRAY_TYPE_P (type))
2250 if (TREE_CODE (type) == POINTER_TYPE)
2251 return descriptor;
2252 else
2254 /* Descriptorless arrays. */
2255 return gfc_build_addr_expr (NULL_TREE, descriptor);
2258 else
2259 return gfc_conv_descriptor_data_get (descriptor);
2263 /* Return an expression for the base offset of an array. */
2265 tree
2266 gfc_conv_array_offset (tree descriptor)
2268 tree type;
2270 type = TREE_TYPE (descriptor);
2271 if (GFC_ARRAY_TYPE_P (type))
2272 return GFC_TYPE_ARRAY_OFFSET (type);
2273 else
2274 return gfc_conv_descriptor_offset_get (descriptor);
2278 /* Get an expression for the array stride. */
2280 tree
2281 gfc_conv_array_stride (tree descriptor, int dim)
2283 tree tmp;
2284 tree type;
2286 type = TREE_TYPE (descriptor);
2288 /* For descriptorless arrays use the array size. */
2289 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2290 if (tmp != NULL_TREE)
2291 return tmp;
2293 tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
2294 return tmp;
2298 /* Like gfc_conv_array_stride, but for the lower bound. */
2300 tree
2301 gfc_conv_array_lbound (tree descriptor, int dim)
2303 tree tmp;
2304 tree type;
2306 type = TREE_TYPE (descriptor);
2308 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2309 if (tmp != NULL_TREE)
2310 return tmp;
2312 tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
2313 return tmp;
2317 /* Like gfc_conv_array_stride, but for the upper bound. */
2319 tree
2320 gfc_conv_array_ubound (tree descriptor, int dim)
2322 tree tmp;
2323 tree type;
2325 type = TREE_TYPE (descriptor);
2327 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2328 if (tmp != NULL_TREE)
2329 return tmp;
2331 /* This should only ever happen when passing an assumed shape array
2332 as an actual parameter. The value will never be used. */
2333 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
2334 return gfc_index_zero_node;
2336 tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
2337 return tmp;
2341 /* Generate code to perform an array index bound check. */
2343 static tree
2344 gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
2345 locus * where, bool check_upper)
2347 tree fault;
2348 tree tmp_lo, tmp_up;
2349 char *msg;
2350 const char * name = NULL;
2352 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
2353 return index;
2355 index = gfc_evaluate_now (index, &se->pre);
2357 /* We find a name for the error message. */
2358 if (se->ss)
2359 name = se->ss->expr->symtree->name;
2361 if (!name && se->loop && se->loop->ss && se->loop->ss->expr
2362 && se->loop->ss->expr->symtree)
2363 name = se->loop->ss->expr->symtree->name;
2365 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2366 && se->loop->ss->loop_chain->expr
2367 && se->loop->ss->loop_chain->expr->symtree)
2368 name = se->loop->ss->loop_chain->expr->symtree->name;
2370 if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
2372 if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
2373 && se->loop->ss->expr->value.function.name)
2374 name = se->loop->ss->expr->value.function.name;
2375 else
2376 if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
2377 || se->loop->ss->type == GFC_SS_SCALAR)
2378 name = "unnamed constant";
2381 if (TREE_CODE (descriptor) == VAR_DECL)
2382 name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
2384 /* If upper bound is present, include both bounds in the error message. */
2385 if (check_upper)
2387 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2388 tmp_up = gfc_conv_array_ubound (descriptor, n);
2390 if (name)
2391 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2392 "outside of expected range (%%ld:%%ld)", n+1, name);
2393 else
2394 asprintf (&msg, "Index '%%ld' of dimension %d "
2395 "outside of expected range (%%ld:%%ld)", n+1);
2397 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2398 index, tmp_lo);
2399 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2400 fold_convert (long_integer_type_node, index),
2401 fold_convert (long_integer_type_node, tmp_lo),
2402 fold_convert (long_integer_type_node, tmp_up));
2403 fault = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
2404 index, tmp_up);
2405 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2406 fold_convert (long_integer_type_node, index),
2407 fold_convert (long_integer_type_node, tmp_lo),
2408 fold_convert (long_integer_type_node, tmp_up));
2409 gfc_free (msg);
2411 else
2413 tmp_lo = gfc_conv_array_lbound (descriptor, n);
2415 if (name)
2416 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2417 "below lower bound of %%ld", n+1, name);
2418 else
2419 asprintf (&msg, "Index '%%ld' of dimension %d "
2420 "below lower bound of %%ld", n+1);
2422 fault = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2423 index, tmp_lo);
2424 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
2425 fold_convert (long_integer_type_node, index),
2426 fold_convert (long_integer_type_node, tmp_lo));
2427 gfc_free (msg);
2430 return index;
2434 /* Return the offset for an index. Performs bound checking for elemental
2435 dimensions. Single element references are processed separately.
2436 DIM is the array dimension, I is the loop dimension. */
2438 static tree
2439 gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
2440 gfc_array_ref * ar, tree stride)
2442 tree index;
2443 tree desc;
2444 tree data;
2446 /* Get the index into the array for this dimension. */
2447 if (ar)
2449 gcc_assert (ar->type != AR_ELEMENT);
2450 switch (ar->dimen_type[dim])
2452 case DIMEN_ELEMENT:
2453 /* Elemental dimension. */
2454 gcc_assert (info->subscript[dim]
2455 && info->subscript[dim]->type == GFC_SS_SCALAR);
2456 /* We've already translated this value outside the loop. */
2457 index = info->subscript[dim]->data.scalar.expr;
2459 index = gfc_trans_array_bound_check (se, info->descriptor,
2460 index, dim, &ar->where,
2461 ar->as->type != AS_ASSUMED_SIZE
2462 || dim < ar->dimen - 1);
2463 break;
2465 case DIMEN_VECTOR:
2466 gcc_assert (info && se->loop);
2467 gcc_assert (info->subscript[dim]
2468 && info->subscript[dim]->type == GFC_SS_VECTOR);
2469 desc = info->subscript[dim]->data.info.descriptor;
2471 /* Get a zero-based index into the vector. */
2472 index = fold_build2_loc (input_location, MINUS_EXPR,
2473 gfc_array_index_type,
2474 se->loop->loopvar[i], se->loop->from[i]);
2476 /* Multiply the index by the stride. */
2477 index = fold_build2_loc (input_location, MULT_EXPR,
2478 gfc_array_index_type,
2479 index, gfc_conv_array_stride (desc, 0));
2481 /* Read the vector to get an index into info->descriptor. */
2482 data = build_fold_indirect_ref_loc (input_location,
2483 gfc_conv_array_data (desc));
2484 index = gfc_build_array_ref (data, index, NULL);
2485 index = gfc_evaluate_now (index, &se->pre);
2486 index = fold_convert (gfc_array_index_type, index);
2488 /* Do any bounds checking on the final info->descriptor index. */
2489 index = gfc_trans_array_bound_check (se, info->descriptor,
2490 index, dim, &ar->where,
2491 ar->as->type != AS_ASSUMED_SIZE
2492 || dim < ar->dimen - 1);
2493 break;
2495 case DIMEN_RANGE:
2496 /* Scalarized dimension. */
2497 gcc_assert (info && se->loop);
2499 /* Multiply the loop variable by the stride and delta. */
2500 index = se->loop->loopvar[i];
2501 if (!integer_onep (info->stride[dim]))
2502 index = fold_build2_loc (input_location, MULT_EXPR,
2503 gfc_array_index_type, index,
2504 info->stride[dim]);
2505 if (!integer_zerop (info->delta[dim]))
2506 index = fold_build2_loc (input_location, PLUS_EXPR,
2507 gfc_array_index_type, index,
2508 info->delta[dim]);
2509 break;
2511 default:
2512 gcc_unreachable ();
2515 else
2517 /* Temporary array or derived type component. */
2518 gcc_assert (se->loop);
2519 index = se->loop->loopvar[se->loop->order[i]];
2520 if (!integer_zerop (info->delta[dim]))
2521 index = fold_build2_loc (input_location, PLUS_EXPR,
2522 gfc_array_index_type, index, info->delta[dim]);
2525 /* Multiply by the stride. */
2526 if (!integer_onep (stride))
2527 index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2528 index, stride);
2530 return index;
2534 /* Build a scalarized reference to an array. */
2536 static void
2537 gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2539 gfc_ss_info *info;
2540 tree decl = NULL_TREE;
2541 tree index;
2542 tree tmp;
2543 int n;
2545 info = &se->ss->data.info;
2546 if (ar)
2547 n = se->loop->order[0];
2548 else
2549 n = 0;
2551 index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
2552 info->stride0);
2553 /* Add the offset for this dimension to the stored offset for all other
2554 dimensions. */
2555 if (!integer_zerop (info->offset))
2556 index = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2557 index, info->offset);
2559 if (se->ss->expr && is_subref_array (se->ss->expr))
2560 decl = se->ss->expr->symtree->n.sym->backend_decl;
2562 tmp = build_fold_indirect_ref_loc (input_location,
2563 info->data);
2564 se->expr = gfc_build_array_ref (tmp, index, decl);
2568 /* Translate access of temporary array. */
2570 void
2571 gfc_conv_tmp_array_ref (gfc_se * se)
2573 se->string_length = se->ss->string_length;
2574 gfc_conv_scalarized_array_ref (se, NULL);
2575 gfc_advance_se_ss_chain (se);
2579 /* Build an array reference. se->expr already holds the array descriptor.
2580 This should be either a variable, indirect variable reference or component
2581 reference. For arrays which do not have a descriptor, se->expr will be
2582 the data pointer.
2583 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2585 void
2586 gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2587 locus * where)
2589 int n;
2590 tree index;
2591 tree tmp;
2592 tree stride;
2593 gfc_se indexse;
2594 gfc_se tmpse;
2596 if (ar->dimen == 0)
2597 return;
2599 /* Handle scalarized references separately. */
2600 if (ar->type != AR_ELEMENT)
2602 gfc_conv_scalarized_array_ref (se, ar);
2603 gfc_advance_se_ss_chain (se);
2604 return;
2607 index = gfc_index_zero_node;
2609 /* Calculate the offsets from all the dimensions. */
2610 for (n = 0; n < ar->dimen; n++)
2612 /* Calculate the index for this dimension. */
2613 gfc_init_se (&indexse, se);
2614 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2615 gfc_add_block_to_block (&se->pre, &indexse.pre);
2617 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2619 /* Check array bounds. */
2620 tree cond;
2621 char *msg;
2623 /* Evaluate the indexse.expr only once. */
2624 indexse.expr = save_expr (indexse.expr);
2626 /* Lower bound. */
2627 tmp = gfc_conv_array_lbound (se->expr, n);
2628 if (sym->attr.temporary)
2630 gfc_init_se (&tmpse, se);
2631 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
2632 gfc_array_index_type);
2633 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2634 tmp = tmpse.expr;
2637 cond = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
2638 indexse.expr, tmp);
2639 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2640 "below lower bound of %%ld", n+1, sym->name);
2641 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2642 fold_convert (long_integer_type_node,
2643 indexse.expr),
2644 fold_convert (long_integer_type_node, tmp));
2645 gfc_free (msg);
2647 /* Upper bound, but not for the last dimension of assumed-size
2648 arrays. */
2649 if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
2651 tmp = gfc_conv_array_ubound (se->expr, n);
2652 if (sym->attr.temporary)
2654 gfc_init_se (&tmpse, se);
2655 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
2656 gfc_array_index_type);
2657 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2658 tmp = tmpse.expr;
2661 cond = fold_build2_loc (input_location, GT_EXPR,
2662 boolean_type_node, indexse.expr, tmp);
2663 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
2664 "above upper bound of %%ld", n+1, sym->name);
2665 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
2666 fold_convert (long_integer_type_node,
2667 indexse.expr),
2668 fold_convert (long_integer_type_node, tmp));
2669 gfc_free (msg);
2673 /* Multiply the index by the stride. */
2674 stride = gfc_conv_array_stride (se->expr, n);
2675 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
2676 indexse.expr, stride);
2678 /* And add it to the total. */
2679 index = fold_build2_loc (input_location, PLUS_EXPR,
2680 gfc_array_index_type, index, tmp);
2683 tmp = gfc_conv_array_offset (se->expr);
2684 if (!integer_zerop (tmp))
2685 index = fold_build2_loc (input_location, PLUS_EXPR,
2686 gfc_array_index_type, index, tmp);
2688 /* Access the calculated element. */
2689 tmp = gfc_conv_array_data (se->expr);
2690 tmp = build_fold_indirect_ref (tmp);
2691 se->expr = gfc_build_array_ref (tmp, index, sym->backend_decl);
2695 /* Generate the code to be executed immediately before entering a
2696 scalarization loop. */
2698 static void
2699 gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2700 stmtblock_t * pblock)
2702 tree index;
2703 tree stride;
2704 gfc_ss_info *info;
2705 gfc_ss *ss;
2706 gfc_se se;
2707 int i;
2709 /* This code will be executed before entering the scalarization loop
2710 for this dimension. */
2711 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2713 if ((ss->useflags & flag) == 0)
2714 continue;
2716 if (ss->type != GFC_SS_SECTION
2717 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2718 && ss->type != GFC_SS_COMPONENT)
2719 continue;
2721 info = &ss->data.info;
2723 if (dim >= info->dimen)
2724 continue;
2726 if (dim == info->dimen - 1)
2728 /* For the outermost loop calculate the offset due to any
2729 elemental dimensions. It will have been initialized with the
2730 base offset of the array. */
2731 if (info->ref)
2733 for (i = 0; i < info->ref->u.ar.dimen; i++)
2735 if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2736 continue;
2738 gfc_init_se (&se, NULL);
2739 se.loop = loop;
2740 se.expr = info->descriptor;
2741 stride = gfc_conv_array_stride (info->descriptor, i);
2742 index = gfc_conv_array_index_offset (&se, info, i, -1,
2743 &info->ref->u.ar,
2744 stride);
2745 gfc_add_block_to_block (pblock, &se.pre);
2747 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
2748 gfc_array_index_type,
2749 info->offset, index);
2750 info->offset = gfc_evaluate_now (info->offset, pblock);
2754 i = loop->order[0];
2755 /* For the time being, the innermost loop is unconditionally on
2756 the first dimension of the scalarization loop. */
2757 gcc_assert (i == 0);
2758 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2760 /* Calculate the stride of the innermost loop. Hopefully this will
2761 allow the backend optimizers to do their stuff more effectively.
2763 info->stride0 = gfc_evaluate_now (stride, pblock);
2765 else
2767 /* Add the offset for the previous loop dimension. */
2768 gfc_array_ref *ar;
2770 if (info->ref)
2772 ar = &info->ref->u.ar;
2773 i = loop->order[dim + 1];
2775 else
2777 ar = NULL;
2778 i = dim + 1;
2781 gfc_init_se (&se, NULL);
2782 se.loop = loop;
2783 se.expr = info->descriptor;
2784 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2785 index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
2786 ar, stride);
2787 gfc_add_block_to_block (pblock, &se.pre);
2788 info->offset = fold_build2_loc (input_location, PLUS_EXPR,
2789 gfc_array_index_type, info->offset,
2790 index);
2791 info->offset = gfc_evaluate_now (info->offset, pblock);
2794 /* Remember this offset for the second loop. */
2795 if (dim == loop->temp_dim - 1)
2796 info->saved_offset = info->offset;
2801 /* Start a scalarized expression. Creates a scope and declares loop
2802 variables. */
2804 void
2805 gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2807 int dim;
2808 int n;
2809 int flags;
2811 gcc_assert (!loop->array_parameter);
2813 for (dim = loop->dimen - 1; dim >= 0; dim--)
2815 n = loop->order[dim];
2817 gfc_start_block (&loop->code[n]);
2819 /* Create the loop variable. */
2820 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2822 if (dim < loop->temp_dim)
2823 flags = 3;
2824 else
2825 flags = 1;
2826 /* Calculate values that will be constant within this loop. */
2827 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
2829 gfc_start_block (pbody);
2833 /* Generates the actual loop code for a scalarization loop. */
2835 void
2836 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
2837 stmtblock_t * pbody)
2839 stmtblock_t block;
2840 tree cond;
2841 tree tmp;
2842 tree loopbody;
2843 tree exit_label;
2844 tree stmt;
2845 tree init;
2846 tree incr;
2848 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
2849 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
2850 && n == loop->dimen - 1)
2852 /* We create an OMP_FOR construct for the outermost scalarized loop. */
2853 init = make_tree_vec (1);
2854 cond = make_tree_vec (1);
2855 incr = make_tree_vec (1);
2857 /* Cycle statement is implemented with a goto. Exit statement must not
2858 be present for this loop. */
2859 exit_label = gfc_build_label_decl (NULL_TREE);
2860 TREE_USED (exit_label) = 1;
2862 /* Label for cycle statements (if needed). */
2863 tmp = build1_v (LABEL_EXPR, exit_label);
2864 gfc_add_expr_to_block (pbody, tmp);
2866 stmt = make_node (OMP_FOR);
2868 TREE_TYPE (stmt) = void_type_node;
2869 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
2871 OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
2872 OMP_CLAUSE_SCHEDULE);
2873 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
2874 = OMP_CLAUSE_SCHEDULE_STATIC;
2875 if (ompws_flags & OMPWS_NOWAIT)
2876 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
2877 = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
2879 /* Initialize the loopvar. */
2880 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
2881 loop->from[n]);
2882 OMP_FOR_INIT (stmt) = init;
2883 /* The exit condition. */
2884 TREE_VEC_ELT (cond, 0) = build2_loc (input_location, LE_EXPR,
2885 boolean_type_node,
2886 loop->loopvar[n], loop->to[n]);
2887 SET_EXPR_LOCATION (TREE_VEC_ELT (cond, 0), input_location);
2888 OMP_FOR_COND (stmt) = cond;
2889 /* Increment the loopvar. */
2890 tmp = build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2891 loop->loopvar[n], gfc_index_one_node);
2892 TREE_VEC_ELT (incr, 0) = fold_build2_loc (input_location, MODIFY_EXPR,
2893 void_type_node, loop->loopvar[n], tmp);
2894 OMP_FOR_INCR (stmt) = incr;
2896 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
2897 gfc_add_expr_to_block (&loop->code[n], stmt);
2899 else
2901 bool reverse_loop = (loop->reverse[n] == GFC_REVERSE_SET)
2902 && (loop->temp_ss == NULL);
2904 loopbody = gfc_finish_block (pbody);
2906 if (reverse_loop)
2908 tmp = loop->from[n];
2909 loop->from[n] = loop->to[n];
2910 loop->to[n] = tmp;
2913 /* Initialize the loopvar. */
2914 if (loop->loopvar[n] != loop->from[n])
2915 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
2917 exit_label = gfc_build_label_decl (NULL_TREE);
2919 /* Generate the loop body. */
2920 gfc_init_block (&block);
2922 /* The exit condition. */
2923 cond = fold_build2_loc (input_location, reverse_loop ? LT_EXPR : GT_EXPR,
2924 boolean_type_node, loop->loopvar[n], loop->to[n]);
2925 tmp = build1_v (GOTO_EXPR, exit_label);
2926 TREE_USED (exit_label) = 1;
2927 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
2928 gfc_add_expr_to_block (&block, tmp);
2930 /* The main body. */
2931 gfc_add_expr_to_block (&block, loopbody);
2933 /* Increment the loopvar. */
2934 tmp = fold_build2_loc (input_location,
2935 reverse_loop ? MINUS_EXPR : PLUS_EXPR,
2936 gfc_array_index_type, loop->loopvar[n],
2937 gfc_index_one_node);
2939 gfc_add_modify (&block, loop->loopvar[n], tmp);
2941 /* Build the loop. */
2942 tmp = gfc_finish_block (&block);
2943 tmp = build1_v (LOOP_EXPR, tmp);
2944 gfc_add_expr_to_block (&loop->code[n], tmp);
2946 /* Add the exit label. */
2947 tmp = build1_v (LABEL_EXPR, exit_label);
2948 gfc_add_expr_to_block (&loop->code[n], tmp);
2954 /* Finishes and generates the loops for a scalarized expression. */
2956 void
2957 gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
2959 int dim;
2960 int n;
2961 gfc_ss *ss;
2962 stmtblock_t *pblock;
2963 tree tmp;
2965 pblock = body;
2966 /* Generate the loops. */
2967 for (dim = 0; dim < loop->dimen; dim++)
2969 n = loop->order[dim];
2970 gfc_trans_scalarized_loop_end (loop, n, pblock);
2971 loop->loopvar[n] = NULL_TREE;
2972 pblock = &loop->code[n];
2975 tmp = gfc_finish_block (pblock);
2976 gfc_add_expr_to_block (&loop->pre, tmp);
2978 /* Clear all the used flags. */
2979 for (ss = loop->ss; ss; ss = ss->loop_chain)
2980 ss->useflags = 0;
2984 /* Finish the main body of a scalarized expression, and start the secondary
2985 copying body. */
2987 void
2988 gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
2990 int dim;
2991 int n;
2992 stmtblock_t *pblock;
2993 gfc_ss *ss;
2995 pblock = body;
2996 /* We finish as many loops as are used by the temporary. */
2997 for (dim = 0; dim < loop->temp_dim - 1; dim++)
2999 n = loop->order[dim];
3000 gfc_trans_scalarized_loop_end (loop, n, pblock);
3001 loop->loopvar[n] = NULL_TREE;
3002 pblock = &loop->code[n];
3005 /* We don't want to finish the outermost loop entirely. */
3006 n = loop->order[loop->temp_dim - 1];
3007 gfc_trans_scalarized_loop_end (loop, n, pblock);
3009 /* Restore the initial offsets. */
3010 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3012 if ((ss->useflags & 2) == 0)
3013 continue;
3015 if (ss->type != GFC_SS_SECTION
3016 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
3017 && ss->type != GFC_SS_COMPONENT)
3018 continue;
3020 ss->data.info.offset = ss->data.info.saved_offset;
3023 /* Restart all the inner loops we just finished. */
3024 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
3026 n = loop->order[dim];
3028 gfc_start_block (&loop->code[n]);
3030 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
3032 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
3035 /* Start a block for the secondary copying code. */
3036 gfc_start_block (body);
3040 /* Calculate the lower bound of an array section. */
3042 static void
3043 gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
3045 gfc_expr *start;
3046 gfc_expr *end;
3047 gfc_expr *stride;
3048 tree desc;
3049 gfc_se se;
3050 gfc_ss_info *info;
3052 gcc_assert (ss->type == GFC_SS_SECTION);
3054 info = &ss->data.info;
3056 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3058 /* We use a zero-based index to access the vector. */
3059 info->start[dim] = gfc_index_zero_node;
3060 info->stride[dim] = gfc_index_one_node;
3061 info->end[dim] = NULL;
3062 return;
3065 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
3066 desc = info->descriptor;
3067 start = info->ref->u.ar.start[dim];
3068 end = info->ref->u.ar.end[dim];
3069 stride = info->ref->u.ar.stride[dim];
3071 /* Calculate the start of the range. For vector subscripts this will
3072 be the range of the vector. */
3073 if (start)
3075 /* Specified section start. */
3076 gfc_init_se (&se, NULL);
3077 gfc_conv_expr_type (&se, start, gfc_array_index_type);
3078 gfc_add_block_to_block (&loop->pre, &se.pre);
3079 info->start[dim] = se.expr;
3081 else
3083 /* No lower bound specified so use the bound of the array. */
3084 info->start[dim] = gfc_conv_array_lbound (desc, dim);
3086 info->start[dim] = gfc_evaluate_now (info->start[dim], &loop->pre);
3088 /* Similarly calculate the end. Although this is not used in the
3089 scalarizer, it is needed when checking bounds and where the end
3090 is an expression with side-effects. */
3091 if (end)
3093 /* Specified section start. */
3094 gfc_init_se (&se, NULL);
3095 gfc_conv_expr_type (&se, end, gfc_array_index_type);
3096 gfc_add_block_to_block (&loop->pre, &se.pre);
3097 info->end[dim] = se.expr;
3099 else
3101 /* No upper bound specified so use the bound of the array. */
3102 info->end[dim] = gfc_conv_array_ubound (desc, dim);
3104 info->end[dim] = gfc_evaluate_now (info->end[dim], &loop->pre);
3106 /* Calculate the stride. */
3107 if (stride == NULL)
3108 info->stride[dim] = gfc_index_one_node;
3109 else
3111 gfc_init_se (&se, NULL);
3112 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3113 gfc_add_block_to_block (&loop->pre, &se.pre);
3114 info->stride[dim] = gfc_evaluate_now (se.expr, &loop->pre);
3119 /* Calculates the range start and stride for a SS chain. Also gets the
3120 descriptor and data pointer. The range of vector subscripts is the size
3121 of the vector. Array bounds are also checked. */
3123 void
3124 gfc_conv_ss_startstride (gfc_loopinfo * loop)
3126 int n;
3127 tree tmp;
3128 gfc_ss *ss;
3129 tree desc;
3131 loop->dimen = 0;
3132 /* Determine the rank of the loop. */
3133 for (ss = loop->ss;
3134 ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
3136 switch (ss->type)
3138 case GFC_SS_SECTION:
3139 case GFC_SS_CONSTRUCTOR:
3140 case GFC_SS_FUNCTION:
3141 case GFC_SS_COMPONENT:
3142 loop->dimen = ss->data.info.dimen;
3143 break;
3145 /* As usual, lbound and ubound are exceptions!. */
3146 case GFC_SS_INTRINSIC:
3147 switch (ss->expr->value.function.isym->id)
3149 case GFC_ISYM_LBOUND:
3150 case GFC_ISYM_UBOUND:
3151 loop->dimen = ss->data.info.dimen;
3153 default:
3154 break;
3157 default:
3158 break;
3162 /* We should have determined the rank of the expression by now. If
3163 not, that's bad news. */
3164 gcc_assert (loop->dimen != 0);
3166 /* Loop over all the SS in the chain. */
3167 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3169 if (ss->expr && ss->expr->shape && !ss->shape)
3170 ss->shape = ss->expr->shape;
3172 switch (ss->type)
3174 case GFC_SS_SECTION:
3175 /* Get the descriptor for the array. */
3176 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
3178 for (n = 0; n < ss->data.info.dimen; n++)
3179 gfc_conv_section_startstride (loop, ss, ss->data.info.dim[n]);
3180 break;
3182 case GFC_SS_INTRINSIC:
3183 switch (ss->expr->value.function.isym->id)
3185 /* Fall through to supply start and stride. */
3186 case GFC_ISYM_LBOUND:
3187 case GFC_ISYM_UBOUND:
3188 break;
3189 default:
3190 continue;
3193 case GFC_SS_CONSTRUCTOR:
3194 case GFC_SS_FUNCTION:
3195 for (n = 0; n < ss->data.info.dimen; n++)
3197 ss->data.info.start[n] = gfc_index_zero_node;
3198 ss->data.info.end[n] = gfc_index_zero_node;
3199 ss->data.info.stride[n] = gfc_index_one_node;
3201 break;
3203 default:
3204 break;
3208 /* The rest is just runtime bound checking. */
3209 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3211 stmtblock_t block;
3212 tree lbound, ubound;
3213 tree end;
3214 tree size[GFC_MAX_DIMENSIONS];
3215 tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
3216 gfc_ss_info *info;
3217 char *msg;
3218 int dim;
3220 gfc_start_block (&block);
3222 for (n = 0; n < loop->dimen; n++)
3223 size[n] = NULL_TREE;
3225 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3227 stmtblock_t inner;
3229 if (ss->type != GFC_SS_SECTION)
3230 continue;
3232 /* Catch allocatable lhs in f2003. */
3233 if (gfc_option.flag_realloc_lhs && ss->is_alloc_lhs)
3234 continue;
3236 gfc_start_block (&inner);
3238 /* TODO: range checking for mapped dimensions. */
3239 info = &ss->data.info;
3241 /* This code only checks ranges. Elemental and vector
3242 dimensions are checked later. */
3243 for (n = 0; n < loop->dimen; n++)
3245 bool check_upper;
3247 dim = info->dim[n];
3248 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
3249 continue;
3251 if (dim == info->ref->u.ar.dimen - 1
3252 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
3253 check_upper = false;
3254 else
3255 check_upper = true;
3257 /* Zero stride is not allowed. */
3258 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
3259 info->stride[dim], gfc_index_zero_node);
3260 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
3261 "of array '%s'", dim + 1, ss->expr->symtree->name);
3262 gfc_trans_runtime_check (true, false, tmp, &inner,
3263 &ss->expr->where, msg);
3264 gfc_free (msg);
3266 desc = ss->data.info.descriptor;
3268 /* This is the run-time equivalent of resolve.c's
3269 check_dimension(). The logical is more readable there
3270 than it is here, with all the trees. */
3271 lbound = gfc_conv_array_lbound (desc, dim);
3272 end = info->end[dim];
3273 if (check_upper)
3274 ubound = gfc_conv_array_ubound (desc, dim);
3275 else
3276 ubound = NULL;
3278 /* non_zerosized is true when the selected range is not
3279 empty. */
3280 stride_pos = fold_build2_loc (input_location, GT_EXPR,
3281 boolean_type_node, info->stride[dim],
3282 gfc_index_zero_node);
3283 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3284 info->start[dim], end);
3285 stride_pos = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3286 boolean_type_node, stride_pos, tmp);
3288 stride_neg = fold_build2_loc (input_location, LT_EXPR,
3289 boolean_type_node,
3290 info->stride[dim], gfc_index_zero_node);
3291 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
3292 info->start[dim], end);
3293 stride_neg = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3294 boolean_type_node,
3295 stride_neg, tmp);
3296 non_zerosized = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3297 boolean_type_node,
3298 stride_pos, stride_neg);
3300 /* Check the start of the range against the lower and upper
3301 bounds of the array, if the range is not empty.
3302 If upper bound is present, include both bounds in the
3303 error message. */
3304 if (check_upper)
3306 tmp = fold_build2_loc (input_location, LT_EXPR,
3307 boolean_type_node,
3308 info->start[dim], lbound);
3309 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3310 boolean_type_node,
3311 non_zerosized, tmp);
3312 tmp2 = fold_build2_loc (input_location, GT_EXPR,
3313 boolean_type_node,
3314 info->start[dim], ubound);
3315 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3316 boolean_type_node,
3317 non_zerosized, tmp2);
3318 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3319 "outside of expected range (%%ld:%%ld)",
3320 dim + 1, ss->expr->symtree->name);
3321 gfc_trans_runtime_check (true, false, tmp, &inner,
3322 &ss->expr->where, msg,
3323 fold_convert (long_integer_type_node, info->start[dim]),
3324 fold_convert (long_integer_type_node, lbound),
3325 fold_convert (long_integer_type_node, ubound));
3326 gfc_trans_runtime_check (true, false, tmp2, &inner,
3327 &ss->expr->where, msg,
3328 fold_convert (long_integer_type_node, info->start[dim]),
3329 fold_convert (long_integer_type_node, lbound),
3330 fold_convert (long_integer_type_node, ubound));
3331 gfc_free (msg);
3333 else
3335 tmp = fold_build2_loc (input_location, LT_EXPR,
3336 boolean_type_node,
3337 info->start[dim], lbound);
3338 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3339 boolean_type_node, non_zerosized, tmp);
3340 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3341 "below lower bound of %%ld",
3342 dim + 1, ss->expr->symtree->name);
3343 gfc_trans_runtime_check (true, false, tmp, &inner,
3344 &ss->expr->where, msg,
3345 fold_convert (long_integer_type_node, info->start[dim]),
3346 fold_convert (long_integer_type_node, lbound));
3347 gfc_free (msg);
3350 /* Compute the last element of the range, which is not
3351 necessarily "end" (think 0:5:3, which doesn't contain 5)
3352 and check it against both lower and upper bounds. */
3354 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3355 gfc_array_index_type, end,
3356 info->start[dim]);
3357 tmp = fold_build2_loc (input_location, TRUNC_MOD_EXPR,
3358 gfc_array_index_type, tmp,
3359 info->stride[dim]);
3360 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3361 gfc_array_index_type, end, tmp);
3362 tmp2 = fold_build2_loc (input_location, LT_EXPR,
3363 boolean_type_node, tmp, lbound);
3364 tmp2 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3365 boolean_type_node, non_zerosized, tmp2);
3366 if (check_upper)
3368 tmp3 = fold_build2_loc (input_location, GT_EXPR,
3369 boolean_type_node, tmp, ubound);
3370 tmp3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
3371 boolean_type_node, non_zerosized, tmp3);
3372 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3373 "outside of expected range (%%ld:%%ld)",
3374 dim + 1, ss->expr->symtree->name);
3375 gfc_trans_runtime_check (true, false, tmp2, &inner,
3376 &ss->expr->where, msg,
3377 fold_convert (long_integer_type_node, tmp),
3378 fold_convert (long_integer_type_node, ubound),
3379 fold_convert (long_integer_type_node, lbound));
3380 gfc_trans_runtime_check (true, false, tmp3, &inner,
3381 &ss->expr->where, msg,
3382 fold_convert (long_integer_type_node, tmp),
3383 fold_convert (long_integer_type_node, ubound),
3384 fold_convert (long_integer_type_node, lbound));
3385 gfc_free (msg);
3387 else
3389 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
3390 "below lower bound of %%ld",
3391 dim + 1, ss->expr->symtree->name);
3392 gfc_trans_runtime_check (true, false, tmp2, &inner,
3393 &ss->expr->where, msg,
3394 fold_convert (long_integer_type_node, tmp),
3395 fold_convert (long_integer_type_node, lbound));
3396 gfc_free (msg);
3399 /* Check the section sizes match. */
3400 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3401 gfc_array_index_type, end,
3402 info->start[dim]);
3403 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
3404 gfc_array_index_type, tmp,
3405 info->stride[dim]);
3406 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3407 gfc_array_index_type,
3408 gfc_index_one_node, tmp);
3409 tmp = fold_build2_loc (input_location, MAX_EXPR,
3410 gfc_array_index_type, tmp,
3411 build_int_cst (gfc_array_index_type, 0));
3412 /* We remember the size of the first section, and check all the
3413 others against this. */
3414 if (size[n])
3416 tmp3 = fold_build2_loc (input_location, NE_EXPR,
3417 boolean_type_node, tmp, size[n]);
3418 asprintf (&msg, "Array bound mismatch for dimension %d "
3419 "of array '%s' (%%ld/%%ld)",
3420 dim + 1, ss->expr->symtree->name);
3422 gfc_trans_runtime_check (true, false, tmp3, &inner,
3423 &ss->expr->where, msg,
3424 fold_convert (long_integer_type_node, tmp),
3425 fold_convert (long_integer_type_node, size[n]));
3427 gfc_free (msg);
3429 else
3430 size[n] = gfc_evaluate_now (tmp, &inner);
3433 tmp = gfc_finish_block (&inner);
3435 /* For optional arguments, only check bounds if the argument is
3436 present. */
3437 if (ss->expr->symtree->n.sym->attr.optional
3438 || ss->expr->symtree->n.sym->attr.not_always_present)
3439 tmp = build3_v (COND_EXPR,
3440 gfc_conv_expr_present (ss->expr->symtree->n.sym),
3441 tmp, build_empty_stmt (input_location));
3443 gfc_add_expr_to_block (&block, tmp);
3447 tmp = gfc_finish_block (&block);
3448 gfc_add_expr_to_block (&loop->pre, tmp);
3453 /* Return true if the two SS could be aliased, i.e. both point to the same data
3454 object. */
3455 /* TODO: resolve aliases based on frontend expressions. */
3457 static int
3458 gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
3460 gfc_ref *lref;
3461 gfc_ref *rref;
3462 gfc_symbol *lsym;
3463 gfc_symbol *rsym;
3465 lsym = lss->expr->symtree->n.sym;
3466 rsym = rss->expr->symtree->n.sym;
3467 if (gfc_symbols_could_alias (lsym, rsym))
3468 return 1;
3470 if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS
3471 && lsym->ts.type != BT_DERIVED && lsym->ts.type != BT_CLASS)
3472 return 0;
3474 /* For derived types we must check all the component types. We can ignore
3475 array references as these will have the same base type as the previous
3476 component ref. */
3477 for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
3479 if (lref->type != REF_COMPONENT)
3480 continue;
3482 if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
3483 return 1;
3485 for (rref = rss->expr->ref; rref != rss->data.info.ref;
3486 rref = rref->next)
3488 if (rref->type != REF_COMPONENT)
3489 continue;
3491 if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
3492 return 1;
3496 for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
3498 if (rref->type != REF_COMPONENT)
3499 break;
3501 if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
3502 return 1;
3505 return 0;
3509 /* Resolve array data dependencies. Creates a temporary if required. */
3510 /* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
3511 dependency.c. */
3513 void
3514 gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
3515 gfc_ss * rss)
3517 gfc_ss *ss;
3518 gfc_ref *lref;
3519 gfc_ref *rref;
3520 int nDepend = 0;
3521 int i, j;
3523 loop->temp_ss = NULL;
3525 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
3527 if (ss->type != GFC_SS_SECTION)
3528 continue;
3530 if (dest->expr->symtree->n.sym != ss->expr->symtree->n.sym)
3532 if (gfc_could_be_alias (dest, ss)
3533 || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3535 nDepend = 1;
3536 break;
3539 else
3541 lref = dest->expr->ref;
3542 rref = ss->expr->ref;
3544 nDepend = gfc_dep_resolver (lref, rref, &loop->reverse[0]);
3546 if (nDepend == 1)
3547 break;
3549 for (i = 0; i < dest->data.info.dimen; i++)
3550 for (j = 0; j < ss->data.info.dimen; j++)
3551 if (i != j
3552 && dest->data.info.dim[i] == ss->data.info.dim[j])
3554 /* If we don't access array elements in the same order,
3555 there is a dependency. */
3556 nDepend = 1;
3557 goto temporary;
3559 #if 0
3560 /* TODO : loop shifting. */
3561 if (nDepend == 1)
3563 /* Mark the dimensions for LOOP SHIFTING */
3564 for (n = 0; n < loop->dimen; n++)
3566 int dim = dest->data.info.dim[n];
3568 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3569 depends[n] = 2;
3570 else if (! gfc_is_same_range (&lref->u.ar,
3571 &rref->u.ar, dim, 0))
3572 depends[n] = 1;
3575 /* Put all the dimensions with dependencies in the
3576 innermost loops. */
3577 dim = 0;
3578 for (n = 0; n < loop->dimen; n++)
3580 gcc_assert (loop->order[n] == n);
3581 if (depends[n])
3582 loop->order[dim++] = n;
3584 for (n = 0; n < loop->dimen; n++)
3586 if (! depends[n])
3587 loop->order[dim++] = n;
3590 gcc_assert (dim == loop->dimen);
3591 break;
3593 #endif
3597 temporary:
3599 if (nDepend == 1)
3601 tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
3602 if (GFC_ARRAY_TYPE_P (base_type)
3603 || GFC_DESCRIPTOR_TYPE_P (base_type))
3604 base_type = gfc_get_element_type (base_type);
3605 loop->temp_ss = gfc_get_ss ();
3606 loop->temp_ss->type = GFC_SS_TEMP;
3607 loop->temp_ss->data.temp.type = base_type;
3608 loop->temp_ss->string_length = dest->string_length;
3609 loop->temp_ss->data.temp.dimen = loop->dimen;
3610 loop->temp_ss->next = gfc_ss_terminator;
3611 gfc_add_ss_to_loop (loop, loop->temp_ss);
3613 else
3614 loop->temp_ss = NULL;
3618 /* Initialize the scalarization loop. Creates the loop variables. Determines
3619 the range of the loop variables. Creates a temporary if required.
3620 Calculates how to transform from loop variables to array indices for each
3621 expression. Also generates code for scalar expressions which have been
3622 moved outside the loop. */
3624 void
3625 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
3627 int n, dim, spec_dim;
3628 gfc_ss_info *info;
3629 gfc_ss_info *specinfo;
3630 gfc_ss *ss;
3631 tree tmp;
3632 gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
3633 bool dynamic[GFC_MAX_DIMENSIONS];
3634 mpz_t *cshape;
3635 mpz_t i;
3637 mpz_init (i);
3638 for (n = 0; n < loop->dimen; n++)
3640 loopspec[n] = NULL;
3641 dynamic[n] = false;
3642 /* We use one SS term, and use that to determine the bounds of the
3643 loop for this dimension. We try to pick the simplest term. */
3644 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3646 if (ss->type == GFC_SS_SCALAR || ss->type == GFC_SS_REFERENCE)
3647 continue;
3649 info = &ss->data.info;
3650 dim = info->dim[n];
3652 if (loopspec[n] != NULL)
3654 specinfo = &loopspec[n]->data.info;
3655 spec_dim = specinfo->dim[n];
3657 else
3659 /* Silence unitialized warnings. */
3660 specinfo = NULL;
3661 spec_dim = 0;
3664 if (ss->shape)
3666 gcc_assert (ss->shape[dim]);
3667 /* The frontend has worked out the size for us. */
3668 if (!loopspec[n]
3669 || !loopspec[n]->shape
3670 || !integer_zerop (specinfo->start[spec_dim]))
3671 /* Prefer zero-based descriptors if possible. */
3672 loopspec[n] = ss;
3673 continue;
3676 if (ss->type == GFC_SS_CONSTRUCTOR)
3678 gfc_constructor_base base;
3679 /* An unknown size constructor will always be rank one.
3680 Higher rank constructors will either have known shape,
3681 or still be wrapped in a call to reshape. */
3682 gcc_assert (loop->dimen == 1);
3684 /* Always prefer to use the constructor bounds if the size
3685 can be determined at compile time. Prefer not to otherwise,
3686 since the general case involves realloc, and it's better to
3687 avoid that overhead if possible. */
3688 base = ss->expr->value.constructor;
3689 dynamic[n] = gfc_get_array_constructor_size (&i, base);
3690 if (!dynamic[n] || !loopspec[n])
3691 loopspec[n] = ss;
3692 continue;
3695 /* TODO: Pick the best bound if we have a choice between a
3696 function and something else. */
3697 if (ss->type == GFC_SS_FUNCTION)
3699 loopspec[n] = ss;
3700 continue;
3703 /* Avoid using an allocatable lhs in an assignment, since
3704 there might be a reallocation coming. */
3705 if (loopspec[n] && ss->is_alloc_lhs)
3706 continue;
3708 if (ss->type != GFC_SS_SECTION)
3709 continue;
3711 if (!loopspec[n])
3712 loopspec[n] = ss;
3713 /* Criteria for choosing a loop specifier (most important first):
3714 doesn't need realloc
3715 stride of one
3716 known stride
3717 known lower bound
3718 known upper bound
3720 else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
3721 loopspec[n] = ss;
3722 else if (integer_onep (info->stride[dim])
3723 && !integer_onep (specinfo->stride[spec_dim]))
3724 loopspec[n] = ss;
3725 else if (INTEGER_CST_P (info->stride[dim])
3726 && !INTEGER_CST_P (specinfo->stride[spec_dim]))
3727 loopspec[n] = ss;
3728 else if (INTEGER_CST_P (info->start[dim])
3729 && !INTEGER_CST_P (specinfo->start[spec_dim]))
3730 loopspec[n] = ss;
3731 /* We don't work out the upper bound.
3732 else if (INTEGER_CST_P (info->finish[n])
3733 && ! INTEGER_CST_P (specinfo->finish[n]))
3734 loopspec[n] = ss; */
3737 /* We should have found the scalarization loop specifier. If not,
3738 that's bad news. */
3739 gcc_assert (loopspec[n]);
3741 info = &loopspec[n]->data.info;
3742 dim = info->dim[n];
3744 /* Set the extents of this range. */
3745 cshape = loopspec[n]->shape;
3746 if (cshape && INTEGER_CST_P (info->start[dim])
3747 && INTEGER_CST_P (info->stride[dim]))
3749 loop->from[n] = info->start[dim];
3750 mpz_set (i, cshape[get_array_ref_dim (info, n)]);
3751 mpz_sub_ui (i, i, 1);
3752 /* To = from + (size - 1) * stride. */
3753 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
3754 if (!integer_onep (info->stride[dim]))
3755 tmp = fold_build2_loc (input_location, MULT_EXPR,
3756 gfc_array_index_type, tmp,
3757 info->stride[dim]);
3758 loop->to[n] = fold_build2_loc (input_location, PLUS_EXPR,
3759 gfc_array_index_type,
3760 loop->from[n], tmp);
3762 else
3764 loop->from[n] = info->start[dim];
3765 switch (loopspec[n]->type)
3767 case GFC_SS_CONSTRUCTOR:
3768 /* The upper bound is calculated when we expand the
3769 constructor. */
3770 gcc_assert (loop->to[n] == NULL_TREE);
3771 break;
3773 case GFC_SS_SECTION:
3774 /* Use the end expression if it exists and is not constant,
3775 so that it is only evaluated once. */
3776 loop->to[n] = info->end[dim];
3777 break;
3779 case GFC_SS_FUNCTION:
3780 /* The loop bound will be set when we generate the call. */
3781 gcc_assert (loop->to[n] == NULL_TREE);
3782 break;
3784 default:
3785 gcc_unreachable ();
3789 /* Transform everything so we have a simple incrementing variable. */
3790 if (integer_onep (info->stride[dim]))
3791 info->delta[dim] = gfc_index_zero_node;
3792 else
3794 /* Set the delta for this section. */
3795 info->delta[dim] = gfc_evaluate_now (loop->from[n], &loop->pre);
3796 /* Number of iterations is (end - start + step) / step.
3797 with start = 0, this simplifies to
3798 last = end / step;
3799 for (i = 0; i<=last; i++){...}; */
3800 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3801 gfc_array_index_type, loop->to[n],
3802 loop->from[n]);
3803 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR,
3804 gfc_array_index_type, tmp, info->stride[dim]);
3805 tmp = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
3806 tmp, build_int_cst (gfc_array_index_type, -1));
3807 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
3808 /* Make the loop variable start at 0. */
3809 loop->from[n] = gfc_index_zero_node;
3813 /* Add all the scalar code that can be taken out of the loops.
3814 This may include calculating the loop bounds, so do it before
3815 allocating the temporary. */
3816 gfc_add_loop_ss_code (loop, loop->ss, false, where);
3818 /* If we want a temporary then create it. */
3819 if (loop->temp_ss != NULL)
3821 gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
3823 /* Make absolutely sure that this is a complete type. */
3824 if (loop->temp_ss->string_length)
3825 loop->temp_ss->data.temp.type
3826 = gfc_get_character_type_len_for_eltype
3827 (TREE_TYPE (loop->temp_ss->data.temp.type),
3828 loop->temp_ss->string_length);
3830 tmp = loop->temp_ss->data.temp.type;
3831 n = loop->temp_ss->data.temp.dimen;
3832 memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
3833 loop->temp_ss->type = GFC_SS_SECTION;
3834 loop->temp_ss->data.info.dimen = n;
3836 gcc_assert (loop->temp_ss->data.info.dimen != 0);
3837 for (n = 0; n < loop->temp_ss->data.info.dimen; n++)
3838 loop->temp_ss->data.info.dim[n] = n;
3840 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
3841 &loop->temp_ss->data.info, tmp, NULL_TREE,
3842 false, true, false, where);
3845 for (n = 0; n < loop->temp_dim; n++)
3846 loopspec[loop->order[n]] = NULL;
3848 mpz_clear (i);
3850 /* For array parameters we don't have loop variables, so don't calculate the
3851 translations. */
3852 if (loop->array_parameter)
3853 return;
3855 /* Calculate the translation from loop variables to array indices. */
3856 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3858 if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT
3859 && ss->type != GFC_SS_CONSTRUCTOR)
3861 continue;
3863 info = &ss->data.info;
3865 for (n = 0; n < info->dimen; n++)
3867 /* If we are specifying the range the delta is already set. */
3868 if (loopspec[n] != ss)
3870 dim = ss->data.info.dim[n];
3872 /* Calculate the offset relative to the loop variable.
3873 First multiply by the stride. */
3874 tmp = loop->from[n];
3875 if (!integer_onep (info->stride[dim]))
3876 tmp = fold_build2_loc (input_location, MULT_EXPR,
3877 gfc_array_index_type,
3878 tmp, info->stride[dim]);
3880 /* Then subtract this from our starting value. */
3881 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3882 gfc_array_index_type,
3883 info->start[dim], tmp);
3885 info->delta[dim] = gfc_evaluate_now (tmp, &loop->pre);
3892 /* Calculate the size of a given array dimension from the bounds. This
3893 is simply (ubound - lbound + 1) if this expression is positive
3894 or 0 if it is negative (pick either one if it is zero). Optionally
3895 (if or_expr is present) OR the (expression != 0) condition to it. */
3897 tree
3898 gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
3900 tree res;
3901 tree cond;
3903 /* Calculate (ubound - lbound + 1). */
3904 res = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3905 ubound, lbound);
3906 res = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, res,
3907 gfc_index_one_node);
3909 /* Check whether the size for this dimension is negative. */
3910 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, res,
3911 gfc_index_zero_node);
3912 res = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond,
3913 gfc_index_zero_node, res);
3915 /* Build OR expression. */
3916 if (or_expr)
3917 *or_expr = fold_build2_loc (input_location, TRUTH_OR_EXPR,
3918 boolean_type_node, *or_expr, cond);
3920 return res;
3924 /* For an array descriptor, get the total number of elements. This is just
3925 the product of the extents along all dimensions. */
3927 tree
3928 gfc_conv_descriptor_size (tree desc, int rank)
3930 tree res;
3931 int dim;
3933 res = gfc_index_one_node;
3935 for (dim = 0; dim < rank; ++dim)
3937 tree lbound;
3938 tree ubound;
3939 tree extent;
3941 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
3942 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
3944 extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
3945 res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3946 res, extent);
3949 return res;
3953 /* Helper function for marking a boolean expression tree as unlikely. */
3955 static tree
3956 gfc_unlikely (tree cond)
3958 tree tmp;
3960 cond = fold_convert (long_integer_type_node, cond);
3961 tmp = build_zero_cst (long_integer_type_node);
3962 cond = build_call_expr_loc (input_location,
3963 built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
3964 cond = fold_convert (boolean_type_node, cond);
3965 return cond;
3968 /* Fills in an array descriptor, and returns the size of the array.
3969 The size will be a simple_val, ie a variable or a constant. Also
3970 calculates the offset of the base. The pointer argument overflow,
3971 which should be of integer type, will increase in value if overflow
3972 occurs during the size calculation. Returns the size of the array.
3974 stride = 1;
3975 offset = 0;
3976 for (n = 0; n < rank; n++)
3978 a.lbound[n] = specified_lower_bound;
3979 offset = offset + a.lbond[n] * stride;
3980 size = 1 - lbound;
3981 a.ubound[n] = specified_upper_bound;
3982 a.stride[n] = stride;
3983 size = siz >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
3984 overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
3985 stride = stride * size;
3987 element_size = sizeof (array element);
3988 stride = (size_t) stride;
3989 overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
3990 stride = stride * element_size;
3991 return (stride);
3992 } */
3993 /*GCC ARRAYS*/
3995 static tree
3996 gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
3997 gfc_expr ** lower, gfc_expr ** upper,
3998 stmtblock_t * pblock, tree * overflow)
4000 tree type;
4001 tree tmp;
4002 tree size;
4003 tree offset;
4004 tree stride;
4005 tree element_size;
4006 tree or_expr;
4007 tree thencase;
4008 tree elsecase;
4009 tree cond;
4010 tree var;
4011 stmtblock_t thenblock;
4012 stmtblock_t elseblock;
4013 gfc_expr *ubound;
4014 gfc_se se;
4015 int n;
4017 type = TREE_TYPE (descriptor);
4019 stride = gfc_index_one_node;
4020 offset = gfc_index_zero_node;
4022 /* Set the dtype. */
4023 tmp = gfc_conv_descriptor_dtype (descriptor);
4024 gfc_add_modify (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
4026 or_expr = boolean_false_node;
4028 for (n = 0; n < rank; n++)
4030 tree conv_lbound;
4031 tree conv_ubound;
4033 /* We have 3 possibilities for determining the size of the array:
4034 lower == NULL => lbound = 1, ubound = upper[n]
4035 upper[n] = NULL => lbound = 1, ubound = lower[n]
4036 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
4037 ubound = upper[n];
4039 /* Set lower bound. */
4040 gfc_init_se (&se, NULL);
4041 if (lower == NULL)
4042 se.expr = gfc_index_one_node;
4043 else
4045 gcc_assert (lower[n]);
4046 if (ubound)
4048 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
4049 gfc_add_block_to_block (pblock, &se.pre);
4051 else
4053 se.expr = gfc_index_one_node;
4054 ubound = lower[n];
4057 gfc_conv_descriptor_lbound_set (pblock, descriptor, gfc_rank_cst[n],
4058 se.expr);
4059 conv_lbound = se.expr;
4061 /* Work out the offset for this component. */
4062 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4063 se.expr, stride);
4064 offset = fold_build2_loc (input_location, MINUS_EXPR,
4065 gfc_array_index_type, offset, tmp);
4067 /* Set upper bound. */
4068 gfc_init_se (&se, NULL);
4069 gcc_assert (ubound);
4070 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
4071 gfc_add_block_to_block (pblock, &se.pre);
4073 gfc_conv_descriptor_ubound_set (pblock, descriptor,
4074 gfc_rank_cst[n], se.expr);
4075 conv_ubound = se.expr;
4077 /* Store the stride. */
4078 gfc_conv_descriptor_stride_set (pblock, descriptor,
4079 gfc_rank_cst[n], stride);
4081 /* Calculate size and check whether extent is negative. */
4082 size = gfc_conv_array_extent_dim (conv_lbound, conv_ubound, &or_expr);
4083 size = gfc_evaluate_now (size, pblock);
4085 /* Check whether multiplying the stride by the number of
4086 elements in this dimension would overflow. We must also check
4087 whether the current dimension has zero size in order to avoid
4088 division by zero.
4090 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
4091 gfc_array_index_type,
4092 fold_convert (gfc_array_index_type,
4093 TYPE_MAX_VALUE (gfc_array_index_type)),
4094 size);
4095 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
4096 boolean_type_node, tmp, stride));
4097 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4098 integer_one_node, integer_zero_node);
4099 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
4100 boolean_type_node, size,
4101 gfc_index_zero_node));
4102 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4103 integer_zero_node, tmp);
4104 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
4105 *overflow, tmp);
4106 *overflow = gfc_evaluate_now (tmp, pblock);
4108 /* Multiply the stride by the number of elements in this dimension. */
4109 stride = fold_build2_loc (input_location, MULT_EXPR,
4110 gfc_array_index_type, stride, size);
4111 stride = gfc_evaluate_now (stride, pblock);
4114 for (n = rank; n < rank + corank; n++)
4116 ubound = upper[n];
4118 /* Set lower bound. */
4119 gfc_init_se (&se, NULL);
4120 if (lower == NULL || lower[n] == NULL)
4122 gcc_assert (n == rank + corank - 1);
4123 se.expr = gfc_index_one_node;
4125 else
4127 if (ubound || n == rank + corank - 1)
4129 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
4130 gfc_add_block_to_block (pblock, &se.pre);
4132 else
4134 se.expr = gfc_index_one_node;
4135 ubound = lower[n];
4138 gfc_conv_descriptor_lbound_set (pblock, descriptor, gfc_rank_cst[n],
4139 se.expr);
4141 if (n < rank + corank - 1)
4143 gfc_init_se (&se, NULL);
4144 gcc_assert (ubound);
4145 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
4146 gfc_add_block_to_block (pblock, &se.pre);
4147 gfc_conv_descriptor_ubound_set (pblock, descriptor,
4148 gfc_rank_cst[n], se.expr);
4152 /* The stride is the number of elements in the array, so multiply by the
4153 size of an element to get the total size. */
4154 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4155 /* Convert to size_t. */
4156 element_size = fold_convert (size_type_node, tmp);
4157 stride = fold_convert (size_type_node, stride);
4159 /* First check for overflow. Since an array of type character can
4160 have zero element_size, we must check for that before
4161 dividing. */
4162 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
4163 size_type_node,
4164 TYPE_MAX_VALUE (size_type_node), element_size);
4165 cond = gfc_unlikely (fold_build2_loc (input_location, LT_EXPR,
4166 boolean_type_node, tmp, stride));
4167 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4168 integer_one_node, integer_zero_node);
4169 cond = gfc_unlikely (fold_build2_loc (input_location, EQ_EXPR,
4170 boolean_type_node, element_size,
4171 build_int_cst (size_type_node, 0)));
4172 tmp = fold_build3_loc (input_location, COND_EXPR, integer_type_node, cond,
4173 integer_zero_node, tmp);
4174 tmp = fold_build2_loc (input_location, PLUS_EXPR, integer_type_node,
4175 *overflow, tmp);
4176 *overflow = gfc_evaluate_now (tmp, pblock);
4178 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
4179 stride, element_size);
4181 if (poffset != NULL)
4183 offset = gfc_evaluate_now (offset, pblock);
4184 *poffset = offset;
4187 if (integer_zerop (or_expr))
4188 return size;
4189 if (integer_onep (or_expr))
4190 return build_int_cst (size_type_node, 0);
4192 var = gfc_create_var (TREE_TYPE (size), "size");
4193 gfc_start_block (&thenblock);
4194 gfc_add_modify (&thenblock, var, build_int_cst (size_type_node, 0));
4195 thencase = gfc_finish_block (&thenblock);
4197 gfc_start_block (&elseblock);
4198 gfc_add_modify (&elseblock, var, size);
4199 elsecase = gfc_finish_block (&elseblock);
4201 tmp = gfc_evaluate_now (or_expr, pblock);
4202 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
4203 gfc_add_expr_to_block (pblock, tmp);
4205 return var;
4209 /* Initializes the descriptor and generates a call to _gfor_allocate. Does
4210 the work for an ALLOCATE statement. */
4211 /*GCC ARRAYS*/
4213 bool
4214 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
4216 tree tmp;
4217 tree pointer;
4218 tree offset;
4219 tree size;
4220 tree msg;
4221 tree error;
4222 tree overflow; /* Boolean storing whether size calculation overflows. */
4223 tree var_overflow;
4224 tree cond;
4225 stmtblock_t elseblock;
4226 gfc_expr **lower;
4227 gfc_expr **upper;
4228 gfc_ref *ref, *prev_ref = NULL;
4229 bool allocatable_array, coarray;
4231 ref = expr->ref;
4233 /* Find the last reference in the chain. */
4234 while (ref && ref->next != NULL)
4236 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
4237 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
4238 prev_ref = ref;
4239 ref = ref->next;
4242 if (ref == NULL || ref->type != REF_ARRAY)
4243 return false;
4245 if (!prev_ref)
4247 allocatable_array = expr->symtree->n.sym->attr.allocatable;
4248 coarray = expr->symtree->n.sym->attr.codimension;
4250 else
4252 allocatable_array = prev_ref->u.c.component->attr.allocatable;
4253 coarray = prev_ref->u.c.component->attr.codimension;
4256 /* Return if this is a scalar coarray. */
4257 if ((!prev_ref && !expr->symtree->n.sym->attr.dimension)
4258 || (prev_ref && !prev_ref->u.c.component->attr.dimension))
4260 gcc_assert (coarray);
4261 return false;
4264 /* Figure out the size of the array. */
4265 switch (ref->u.ar.type)
4267 case AR_ELEMENT:
4268 if (!coarray)
4270 lower = NULL;
4271 upper = ref->u.ar.start;
4272 break;
4274 /* Fall through. */
4276 case AR_SECTION:
4277 lower = ref->u.ar.start;
4278 upper = ref->u.ar.end;
4279 break;
4281 case AR_FULL:
4282 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
4284 lower = ref->u.ar.as->lower;
4285 upper = ref->u.ar.as->upper;
4286 break;
4288 default:
4289 gcc_unreachable ();
4290 break;
4293 overflow = integer_zero_node;
4294 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
4295 ref->u.ar.as->corank, &offset, lower, upper,
4296 &se->pre, &overflow);
4298 var_overflow = gfc_create_var (integer_type_node, "overflow");
4299 gfc_add_modify (&se->pre, var_overflow, overflow);
4301 /* Generate the block of code handling overflow. */
4302 msg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const
4303 ("Integer overflow when calculating the amount of "
4304 "memory to allocate"));
4305 error = build_call_expr_loc (input_location,
4306 gfor_fndecl_runtime_error, 1, msg);
4308 if (pstat != NULL_TREE && !integer_zerop (pstat))
4310 /* Set the status variable if it's present. */
4311 stmtblock_t set_status_block;
4312 tree status_type = pstat ? TREE_TYPE (TREE_TYPE (pstat)) : NULL_TREE;
4314 gfc_start_block (&set_status_block);
4315 gfc_add_modify (&set_status_block,
4316 fold_build1_loc (input_location, INDIRECT_REF,
4317 status_type, pstat),
4318 build_int_cst (status_type, LIBERROR_ALLOCATION));
4320 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4321 pstat, build_int_cst (TREE_TYPE (pstat), 0));
4322 error = fold_build3_loc (input_location, COND_EXPR, void_type_node, tmp,
4323 error, gfc_finish_block (&set_status_block));
4326 gfc_start_block (&elseblock);
4328 /* Allocate memory to store the data. */
4329 pointer = gfc_conv_descriptor_data_get (se->expr);
4330 STRIP_NOPS (pointer);
4332 /* The allocate_array variants take the old pointer as first argument. */
4333 if (allocatable_array)
4334 tmp = gfc_allocate_array_with_status (&elseblock, pointer, size, pstat, expr);
4335 else
4336 tmp = gfc_allocate_with_status (&elseblock, size, pstat);
4337 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, pointer,
4338 tmp);
4340 gfc_add_expr_to_block (&elseblock, tmp);
4342 cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
4343 var_overflow, integer_zero_node));
4344 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond,
4345 error, gfc_finish_block (&elseblock));
4347 gfc_add_expr_to_block (&se->pre, tmp);
4349 gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
4351 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
4352 && expr->ts.u.derived->attr.alloc_comp)
4354 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, se->expr,
4355 ref->u.ar.as->rank);
4356 gfc_add_expr_to_block (&se->pre, tmp);
4359 return true;
4363 /* Deallocate an array variable. Also used when an allocated variable goes
4364 out of scope. */
4365 /*GCC ARRAYS*/
4367 tree
4368 gfc_array_deallocate (tree descriptor, tree pstat, gfc_expr* expr)
4370 tree var;
4371 tree tmp;
4372 stmtblock_t block;
4374 gfc_start_block (&block);
4375 /* Get a pointer to the data. */
4376 var = gfc_conv_descriptor_data_get (descriptor);
4377 STRIP_NOPS (var);
4379 /* Parameter is the address of the data component. */
4380 tmp = gfc_deallocate_with_status (var, pstat, false, expr);
4381 gfc_add_expr_to_block (&block, tmp);
4383 /* Zero the data pointer. */
4384 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
4385 var, build_int_cst (TREE_TYPE (var), 0));
4386 gfc_add_expr_to_block (&block, tmp);
4388 return gfc_finish_block (&block);
4392 /* Create an array constructor from an initialization expression.
4393 We assume the frontend already did any expansions and conversions. */
4395 tree
4396 gfc_conv_array_initializer (tree type, gfc_expr * expr)
4398 gfc_constructor *c;
4399 tree tmp;
4400 gfc_se se;
4401 HOST_WIDE_INT hi;
4402 unsigned HOST_WIDE_INT lo;
4403 tree index;
4404 VEC(constructor_elt,gc) *v = NULL;
4406 switch (expr->expr_type)
4408 case EXPR_CONSTANT:
4409 case EXPR_STRUCTURE:
4410 /* A single scalar or derived type value. Create an array with all
4411 elements equal to that value. */
4412 gfc_init_se (&se, NULL);
4414 if (expr->expr_type == EXPR_CONSTANT)
4415 gfc_conv_constant (&se, expr);
4416 else
4417 gfc_conv_structure (&se, expr, 1);
4419 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4420 gcc_assert (tmp && INTEGER_CST_P (tmp));
4421 hi = TREE_INT_CST_HIGH (tmp);
4422 lo = TREE_INT_CST_LOW (tmp);
4423 lo++;
4424 if (lo == 0)
4425 hi++;
4426 /* This will probably eat buckets of memory for large arrays. */
4427 while (hi != 0 || lo != 0)
4429 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
4430 if (lo == 0)
4431 hi--;
4432 lo--;
4434 break;
4436 case EXPR_ARRAY:
4437 /* Create a vector of all the elements. */
4438 for (c = gfc_constructor_first (expr->value.constructor);
4439 c; c = gfc_constructor_next (c))
4441 if (c->iterator)
4443 /* Problems occur when we get something like
4444 integer :: a(lots) = (/(i, i=1, lots)/) */
4445 gfc_fatal_error ("The number of elements in the array constructor "
4446 "at %L requires an increase of the allowed %d "
4447 "upper limit. See -fmax-array-constructor "
4448 "option", &expr->where,
4449 gfc_option.flag_max_array_constructor);
4450 return NULL_TREE;
4452 if (mpz_cmp_si (c->offset, 0) != 0)
4453 index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
4454 else
4455 index = NULL_TREE;
4457 gfc_init_se (&se, NULL);
4458 switch (c->expr->expr_type)
4460 case EXPR_CONSTANT:
4461 gfc_conv_constant (&se, c->expr);
4462 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4463 break;
4465 case EXPR_STRUCTURE:
4466 gfc_conv_structure (&se, c->expr, 1);
4467 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4468 break;
4471 default:
4472 /* Catch those occasional beasts that do not simplify
4473 for one reason or another, assuming that if they are
4474 standard defying the frontend will catch them. */
4475 gfc_conv_expr (&se, c->expr);
4476 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4477 break;
4480 break;
4482 case EXPR_NULL:
4483 return gfc_build_null_descriptor (type);
4485 default:
4486 gcc_unreachable ();
4489 /* Create a constructor from the list of elements. */
4490 tmp = build_constructor (type, v);
4491 TREE_CONSTANT (tmp) = 1;
4492 return tmp;
4496 /* Generate code to evaluate non-constant array bounds. Sets *poffset and
4497 returns the size (in elements) of the array. */
4499 static tree
4500 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
4501 stmtblock_t * pblock)
4503 gfc_array_spec *as;
4504 tree size;
4505 tree stride;
4506 tree offset;
4507 tree ubound;
4508 tree lbound;
4509 tree tmp;
4510 gfc_se se;
4512 int dim;
4514 as = sym->as;
4516 size = gfc_index_one_node;
4517 offset = gfc_index_zero_node;
4518 for (dim = 0; dim < as->rank; dim++)
4520 /* Evaluate non-constant array bound expressions. */
4521 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
4522 if (as->lower[dim] && !INTEGER_CST_P (lbound))
4524 gfc_init_se (&se, NULL);
4525 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
4526 gfc_add_block_to_block (pblock, &se.pre);
4527 gfc_add_modify (pblock, lbound, se.expr);
4529 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
4530 if (as->upper[dim] && !INTEGER_CST_P (ubound))
4532 gfc_init_se (&se, NULL);
4533 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
4534 gfc_add_block_to_block (pblock, &se.pre);
4535 gfc_add_modify (pblock, ubound, se.expr);
4537 /* The offset of this dimension. offset = offset - lbound * stride. */
4538 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4539 lbound, size);
4540 offset = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4541 offset, tmp);
4543 /* The size of this dimension, and the stride of the next. */
4544 if (dim + 1 < as->rank)
4545 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
4546 else
4547 stride = GFC_TYPE_ARRAY_SIZE (type);
4549 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
4551 /* Calculate stride = size * (ubound + 1 - lbound). */
4552 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4553 gfc_array_index_type,
4554 gfc_index_one_node, lbound);
4555 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4556 gfc_array_index_type, ubound, tmp);
4557 tmp = fold_build2_loc (input_location, MULT_EXPR,
4558 gfc_array_index_type, size, tmp);
4559 if (stride)
4560 gfc_add_modify (pblock, stride, tmp);
4561 else
4562 stride = gfc_evaluate_now (tmp, pblock);
4564 /* Make sure that negative size arrays are translated
4565 to being zero size. */
4566 tmp = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
4567 stride, gfc_index_zero_node);
4568 tmp = fold_build3_loc (input_location, COND_EXPR,
4569 gfc_array_index_type, tmp,
4570 stride, gfc_index_zero_node);
4571 gfc_add_modify (pblock, stride, tmp);
4574 size = stride;
4577 gfc_trans_vla_type_sizes (sym, pblock);
4579 *poffset = offset;
4580 return size;
4584 /* Generate code to initialize/allocate an array variable. */
4586 void
4587 gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
4588 gfc_wrapped_block * block)
4590 stmtblock_t init;
4591 tree type;
4592 tree tmp;
4593 tree size;
4594 tree offset;
4595 bool onstack;
4597 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
4599 /* Do nothing for USEd variables. */
4600 if (sym->attr.use_assoc)
4601 return;
4603 type = TREE_TYPE (decl);
4604 gcc_assert (GFC_ARRAY_TYPE_P (type));
4605 onstack = TREE_CODE (type) != POINTER_TYPE;
4607 gfc_start_block (&init);
4609 /* Evaluate character string length. */
4610 if (sym->ts.type == BT_CHARACTER
4611 && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
4613 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
4615 gfc_trans_vla_type_sizes (sym, &init);
4617 /* Emit a DECL_EXPR for this variable, which will cause the
4618 gimplifier to allocate storage, and all that good stuff. */
4619 tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl);
4620 gfc_add_expr_to_block (&init, tmp);
4623 if (onstack)
4625 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
4626 return;
4629 type = TREE_TYPE (type);
4631 gcc_assert (!sym->attr.use_assoc);
4632 gcc_assert (!TREE_STATIC (decl));
4633 gcc_assert (!sym->module);
4635 if (sym->ts.type == BT_CHARACTER
4636 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
4637 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
4639 size = gfc_trans_array_bounds (type, sym, &offset, &init);
4641 /* Don't actually allocate space for Cray Pointees. */
4642 if (sym->attr.cray_pointee)
4644 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4645 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
4647 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
4648 return;
4651 /* The size is the number of elements in the array, so multiply by the
4652 size of an element to get the total size. */
4653 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
4654 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4655 size, fold_convert (gfc_array_index_type, tmp));
4657 /* Allocate memory to hold the data. */
4658 tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
4659 gfc_add_modify (&init, decl, tmp);
4661 /* Set offset of the array. */
4662 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4663 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
4665 /* Automatic arrays should not have initializers. */
4666 gcc_assert (!sym->value);
4668 /* Free the temporary. */
4669 tmp = gfc_call_free (convert (pvoid_type_node, decl));
4671 gfc_add_init_cleanup (block, gfc_finish_block (&init), tmp);
4675 /* Generate entry and exit code for g77 calling convention arrays. */
4677 void
4678 gfc_trans_g77_array (gfc_symbol * sym, gfc_wrapped_block * block)
4680 tree parm;
4681 tree type;
4682 locus loc;
4683 tree offset;
4684 tree tmp;
4685 tree stmt;
4686 stmtblock_t init;
4688 gfc_save_backend_locus (&loc);
4689 gfc_set_backend_locus (&sym->declared_at);
4691 /* Descriptor type. */
4692 parm = sym->backend_decl;
4693 type = TREE_TYPE (parm);
4694 gcc_assert (GFC_ARRAY_TYPE_P (type));
4696 gfc_start_block (&init);
4698 if (sym->ts.type == BT_CHARACTER
4699 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
4700 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
4702 /* Evaluate the bounds of the array. */
4703 gfc_trans_array_bounds (type, sym, &offset, &init);
4705 /* Set the offset. */
4706 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
4707 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
4709 /* Set the pointer itself if we aren't using the parameter directly. */
4710 if (TREE_CODE (parm) != PARM_DECL)
4712 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
4713 gfc_add_modify (&init, parm, tmp);
4715 stmt = gfc_finish_block (&init);
4717 gfc_restore_backend_locus (&loc);
4719 /* Add the initialization code to the start of the function. */
4721 if (sym->attr.optional || sym->attr.not_always_present)
4723 tmp = gfc_conv_expr_present (sym);
4724 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
4727 gfc_add_init_cleanup (block, stmt, NULL_TREE);
4731 /* Modify the descriptor of an array parameter so that it has the
4732 correct lower bound. Also move the upper bound accordingly.
4733 If the array is not packed, it will be copied into a temporary.
4734 For each dimension we set the new lower and upper bounds. Then we copy the
4735 stride and calculate the offset for this dimension. We also work out
4736 what the stride of a packed array would be, and see it the two match.
4737 If the array need repacking, we set the stride to the values we just
4738 calculated, recalculate the offset and copy the array data.
4739 Code is also added to copy the data back at the end of the function.
4742 void
4743 gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
4744 gfc_wrapped_block * block)
4746 tree size;
4747 tree type;
4748 tree offset;
4749 locus loc;
4750 stmtblock_t init;
4751 tree stmtInit, stmtCleanup;
4752 tree lbound;
4753 tree ubound;
4754 tree dubound;
4755 tree dlbound;
4756 tree dumdesc;
4757 tree tmp;
4758 tree stride, stride2;
4759 tree stmt_packed;
4760 tree stmt_unpacked;
4761 tree partial;
4762 gfc_se se;
4763 int n;
4764 int checkparm;
4765 int no_repack;
4766 bool optional_arg;
4768 /* Do nothing for pointer and allocatable arrays. */
4769 if (sym->attr.pointer || sym->attr.allocatable)
4770 return;
4772 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
4774 gfc_trans_g77_array (sym, block);
4775 return;
4778 gfc_save_backend_locus (&loc);
4779 gfc_set_backend_locus (&sym->declared_at);
4781 /* Descriptor type. */
4782 type = TREE_TYPE (tmpdesc);
4783 gcc_assert (GFC_ARRAY_TYPE_P (type));
4784 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4785 dumdesc = build_fold_indirect_ref_loc (input_location, dumdesc);
4786 gfc_start_block (&init);
4788 if (sym->ts.type == BT_CHARACTER
4789 && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
4790 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
4792 checkparm = (sym->as->type == AS_EXPLICIT
4793 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
4795 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
4796 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
4798 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
4800 /* For non-constant shape arrays we only check if the first dimension
4801 is contiguous. Repacking higher dimensions wouldn't gain us
4802 anything as we still don't know the array stride. */
4803 partial = gfc_create_var (boolean_type_node, "partial");
4804 TREE_USED (partial) = 1;
4805 tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
4806 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, tmp,
4807 gfc_index_one_node);
4808 gfc_add_modify (&init, partial, tmp);
4810 else
4811 partial = NULL_TREE;
4813 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
4814 here, however I think it does the right thing. */
4815 if (no_repack)
4817 /* Set the first stride. */
4818 stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
4819 stride = gfc_evaluate_now (stride, &init);
4821 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4822 stride, gfc_index_zero_node);
4823 tmp = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4824 tmp, gfc_index_one_node, stride);
4825 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
4826 gfc_add_modify (&init, stride, tmp);
4828 /* Allow the user to disable array repacking. */
4829 stmt_unpacked = NULL_TREE;
4831 else
4833 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
4834 /* A library call to repack the array if necessary. */
4835 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
4836 stmt_unpacked = build_call_expr_loc (input_location,
4837 gfor_fndecl_in_pack, 1, tmp);
4839 stride = gfc_index_one_node;
4841 if (gfc_option.warn_array_temp)
4842 gfc_warning ("Creating array temporary at %L", &loc);
4845 /* This is for the case where the array data is used directly without
4846 calling the repack function. */
4847 if (no_repack || partial != NULL_TREE)
4848 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
4849 else
4850 stmt_packed = NULL_TREE;
4852 /* Assign the data pointer. */
4853 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4855 /* Don't repack unknown shape arrays when the first stride is 1. */
4856 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (stmt_packed),
4857 partial, stmt_packed, stmt_unpacked);
4859 else
4860 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
4861 gfc_add_modify (&init, tmpdesc, fold_convert (type, tmp));
4863 offset = gfc_index_zero_node;
4864 size = gfc_index_one_node;
4866 /* Evaluate the bounds of the array. */
4867 for (n = 0; n < sym->as->rank; n++)
4869 if (checkparm || !sym->as->upper[n])
4871 /* Get the bounds of the actual parameter. */
4872 dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
4873 dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
4875 else
4877 dubound = NULL_TREE;
4878 dlbound = NULL_TREE;
4881 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
4882 if (!INTEGER_CST_P (lbound))
4884 gfc_init_se (&se, NULL);
4885 gfc_conv_expr_type (&se, sym->as->lower[n],
4886 gfc_array_index_type);
4887 gfc_add_block_to_block (&init, &se.pre);
4888 gfc_add_modify (&init, lbound, se.expr);
4891 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
4892 /* Set the desired upper bound. */
4893 if (sym->as->upper[n])
4895 /* We know what we want the upper bound to be. */
4896 if (!INTEGER_CST_P (ubound))
4898 gfc_init_se (&se, NULL);
4899 gfc_conv_expr_type (&se, sym->as->upper[n],
4900 gfc_array_index_type);
4901 gfc_add_block_to_block (&init, &se.pre);
4902 gfc_add_modify (&init, ubound, se.expr);
4905 /* Check the sizes match. */
4906 if (checkparm)
4908 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
4909 char * msg;
4910 tree temp;
4912 temp = fold_build2_loc (input_location, MINUS_EXPR,
4913 gfc_array_index_type, ubound, lbound);
4914 temp = fold_build2_loc (input_location, PLUS_EXPR,
4915 gfc_array_index_type,
4916 gfc_index_one_node, temp);
4917 stride2 = fold_build2_loc (input_location, MINUS_EXPR,
4918 gfc_array_index_type, dubound,
4919 dlbound);
4920 stride2 = fold_build2_loc (input_location, PLUS_EXPR,
4921 gfc_array_index_type,
4922 gfc_index_one_node, stride2);
4923 tmp = fold_build2_loc (input_location, NE_EXPR,
4924 gfc_array_index_type, temp, stride2);
4925 asprintf (&msg, "Dimension %d of array '%s' has extent "
4926 "%%ld instead of %%ld", n+1, sym->name);
4928 gfc_trans_runtime_check (true, false, tmp, &init, &loc, msg,
4929 fold_convert (long_integer_type_node, temp),
4930 fold_convert (long_integer_type_node, stride2));
4932 gfc_free (msg);
4935 else
4937 /* For assumed shape arrays move the upper bound by the same amount
4938 as the lower bound. */
4939 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4940 gfc_array_index_type, dubound, dlbound);
4941 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4942 gfc_array_index_type, tmp, lbound);
4943 gfc_add_modify (&init, ubound, tmp);
4945 /* The offset of this dimension. offset = offset - lbound * stride. */
4946 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4947 lbound, stride);
4948 offset = fold_build2_loc (input_location, MINUS_EXPR,
4949 gfc_array_index_type, offset, tmp);
4951 /* The size of this dimension, and the stride of the next. */
4952 if (n + 1 < sym->as->rank)
4954 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
4956 if (no_repack || partial != NULL_TREE)
4957 stmt_unpacked =
4958 gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
4960 /* Figure out the stride if not a known constant. */
4961 if (!INTEGER_CST_P (stride))
4963 if (no_repack)
4964 stmt_packed = NULL_TREE;
4965 else
4967 /* Calculate stride = size * (ubound + 1 - lbound). */
4968 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4969 gfc_array_index_type,
4970 gfc_index_one_node, lbound);
4971 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4972 gfc_array_index_type, ubound, tmp);
4973 size = fold_build2_loc (input_location, MULT_EXPR,
4974 gfc_array_index_type, size, tmp);
4975 stmt_packed = size;
4978 /* Assign the stride. */
4979 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4980 tmp = fold_build3_loc (input_location, COND_EXPR,
4981 gfc_array_index_type, partial,
4982 stmt_unpacked, stmt_packed);
4983 else
4984 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
4985 gfc_add_modify (&init, stride, tmp);
4988 else
4990 stride = GFC_TYPE_ARRAY_SIZE (type);
4992 if (stride && !INTEGER_CST_P (stride))
4994 /* Calculate size = stride * (ubound + 1 - lbound). */
4995 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4996 gfc_array_index_type,
4997 gfc_index_one_node, lbound);
4998 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4999 gfc_array_index_type,
5000 ubound, tmp);
5001 tmp = fold_build2_loc (input_location, MULT_EXPR,
5002 gfc_array_index_type,
5003 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
5004 gfc_add_modify (&init, stride, tmp);
5009 /* Set the offset. */
5010 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
5011 gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
5013 gfc_trans_vla_type_sizes (sym, &init);
5015 stmtInit = gfc_finish_block (&init);
5017 /* Only do the entry/initialization code if the arg is present. */
5018 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5019 optional_arg = (sym->attr.optional
5020 || (sym->ns->proc_name->attr.entry_master
5021 && sym->attr.dummy));
5022 if (optional_arg)
5024 tmp = gfc_conv_expr_present (sym);
5025 stmtInit = build3_v (COND_EXPR, tmp, stmtInit,
5026 build_empty_stmt (input_location));
5029 /* Cleanup code. */
5030 if (no_repack)
5031 stmtCleanup = NULL_TREE;
5032 else
5034 stmtblock_t cleanup;
5035 gfc_start_block (&cleanup);
5037 if (sym->attr.intent != INTENT_IN)
5039 /* Copy the data back. */
5040 tmp = build_call_expr_loc (input_location,
5041 gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
5042 gfc_add_expr_to_block (&cleanup, tmp);
5045 /* Free the temporary. */
5046 tmp = gfc_call_free (tmpdesc);
5047 gfc_add_expr_to_block (&cleanup, tmp);
5049 stmtCleanup = gfc_finish_block (&cleanup);
5051 /* Only do the cleanup if the array was repacked. */
5052 tmp = build_fold_indirect_ref_loc (input_location, dumdesc);
5053 tmp = gfc_conv_descriptor_data_get (tmp);
5054 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
5055 tmp, tmpdesc);
5056 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
5057 build_empty_stmt (input_location));
5059 if (optional_arg)
5061 tmp = gfc_conv_expr_present (sym);
5062 stmtCleanup = build3_v (COND_EXPR, tmp, stmtCleanup,
5063 build_empty_stmt (input_location));
5067 /* We don't need to free any memory allocated by internal_pack as it will
5068 be freed at the end of the function by pop_context. */
5069 gfc_add_init_cleanup (block, stmtInit, stmtCleanup);
5071 gfc_restore_backend_locus (&loc);
5075 /* Calculate the overall offset, including subreferences. */
5076 static void
5077 gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
5078 bool subref, gfc_expr *expr)
5080 tree tmp;
5081 tree field;
5082 tree stride;
5083 tree index;
5084 gfc_ref *ref;
5085 gfc_se start;
5086 int n;
5088 /* If offset is NULL and this is not a subreferenced array, there is
5089 nothing to do. */
5090 if (offset == NULL_TREE)
5092 if (subref)
5093 offset = gfc_index_zero_node;
5094 else
5095 return;
5098 tmp = gfc_conv_array_data (desc);
5099 tmp = build_fold_indirect_ref_loc (input_location,
5100 tmp);
5101 tmp = gfc_build_array_ref (tmp, offset, NULL);
5103 /* Offset the data pointer for pointer assignments from arrays with
5104 subreferences; e.g. my_integer => my_type(:)%integer_component. */
5105 if (subref)
5107 /* Go past the array reference. */
5108 for (ref = expr->ref; ref; ref = ref->next)
5109 if (ref->type == REF_ARRAY &&
5110 ref->u.ar.type != AR_ELEMENT)
5112 ref = ref->next;
5113 break;
5116 /* Calculate the offset for each subsequent subreference. */
5117 for (; ref; ref = ref->next)
5119 switch (ref->type)
5121 case REF_COMPONENT:
5122 field = ref->u.c.component->backend_decl;
5123 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
5124 tmp = fold_build3_loc (input_location, COMPONENT_REF,
5125 TREE_TYPE (field),
5126 tmp, field, NULL_TREE);
5127 break;
5129 case REF_SUBSTRING:
5130 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
5131 gfc_init_se (&start, NULL);
5132 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
5133 gfc_add_block_to_block (block, &start.pre);
5134 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
5135 break;
5137 case REF_ARRAY:
5138 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
5139 && ref->u.ar.type == AR_ELEMENT);
5141 /* TODO - Add bounds checking. */
5142 stride = gfc_index_one_node;
5143 index = gfc_index_zero_node;
5144 for (n = 0; n < ref->u.ar.dimen; n++)
5146 tree itmp;
5147 tree jtmp;
5149 /* Update the index. */
5150 gfc_init_se (&start, NULL);
5151 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
5152 itmp = gfc_evaluate_now (start.expr, block);
5153 gfc_init_se (&start, NULL);
5154 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
5155 jtmp = gfc_evaluate_now (start.expr, block);
5156 itmp = fold_build2_loc (input_location, MINUS_EXPR,
5157 gfc_array_index_type, itmp, jtmp);
5158 itmp = fold_build2_loc (input_location, MULT_EXPR,
5159 gfc_array_index_type, itmp, stride);
5160 index = fold_build2_loc (input_location, PLUS_EXPR,
5161 gfc_array_index_type, itmp, index);
5162 index = gfc_evaluate_now (index, block);
5164 /* Update the stride. */
5165 gfc_init_se (&start, NULL);
5166 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
5167 itmp = fold_build2_loc (input_location, MINUS_EXPR,
5168 gfc_array_index_type, start.expr,
5169 jtmp);
5170 itmp = fold_build2_loc (input_location, PLUS_EXPR,
5171 gfc_array_index_type,
5172 gfc_index_one_node, itmp);
5173 stride = fold_build2_loc (input_location, MULT_EXPR,
5174 gfc_array_index_type, stride, itmp);
5175 stride = gfc_evaluate_now (stride, block);
5178 /* Apply the index to obtain the array element. */
5179 tmp = gfc_build_array_ref (tmp, index, NULL);
5180 break;
5182 default:
5183 gcc_unreachable ();
5184 break;
5189 /* Set the target data pointer. */
5190 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
5191 gfc_conv_descriptor_data_set (block, parm, offset);
5195 /* gfc_conv_expr_descriptor needs the string length an expression
5196 so that the size of the temporary can be obtained. This is done
5197 by adding up the string lengths of all the elements in the
5198 expression. Function with non-constant expressions have their
5199 string lengths mapped onto the actual arguments using the
5200 interface mapping machinery in trans-expr.c. */
5201 static void
5202 get_array_charlen (gfc_expr *expr, gfc_se *se)
5204 gfc_interface_mapping mapping;
5205 gfc_formal_arglist *formal;
5206 gfc_actual_arglist *arg;
5207 gfc_se tse;
5209 if (expr->ts.u.cl->length
5210 && gfc_is_constant_expr (expr->ts.u.cl->length))
5212 if (!expr->ts.u.cl->backend_decl)
5213 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
5214 return;
5217 switch (expr->expr_type)
5219 case EXPR_OP:
5220 get_array_charlen (expr->value.op.op1, se);
5222 /* For parentheses the expression ts.u.cl is identical. */
5223 if (expr->value.op.op == INTRINSIC_PARENTHESES)
5224 return;
5226 expr->ts.u.cl->backend_decl =
5227 gfc_create_var (gfc_charlen_type_node, "sln");
5229 if (expr->value.op.op2)
5231 get_array_charlen (expr->value.op.op2, se);
5233 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
5235 /* Add the string lengths and assign them to the expression
5236 string length backend declaration. */
5237 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
5238 fold_build2_loc (input_location, PLUS_EXPR,
5239 gfc_charlen_type_node,
5240 expr->value.op.op1->ts.u.cl->backend_decl,
5241 expr->value.op.op2->ts.u.cl->backend_decl));
5243 else
5244 gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
5245 expr->value.op.op1->ts.u.cl->backend_decl);
5246 break;
5248 case EXPR_FUNCTION:
5249 if (expr->value.function.esym == NULL
5250 || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
5252 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
5253 break;
5256 /* Map expressions involving the dummy arguments onto the actual
5257 argument expressions. */
5258 gfc_init_interface_mapping (&mapping);
5259 formal = expr->symtree->n.sym->formal;
5260 arg = expr->value.function.actual;
5262 /* Set se = NULL in the calls to the interface mapping, to suppress any
5263 backend stuff. */
5264 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
5266 if (!arg->expr)
5267 continue;
5268 if (formal->sym)
5269 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
5272 gfc_init_se (&tse, NULL);
5274 /* Build the expression for the character length and convert it. */
5275 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
5277 gfc_add_block_to_block (&se->pre, &tse.pre);
5278 gfc_add_block_to_block (&se->post, &tse.post);
5279 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
5280 tse.expr = fold_build2_loc (input_location, MAX_EXPR,
5281 gfc_charlen_type_node, tse.expr,
5282 build_int_cst (gfc_charlen_type_node, 0));
5283 expr->ts.u.cl->backend_decl = tse.expr;
5284 gfc_free_interface_mapping (&mapping);
5285 break;
5287 default:
5288 gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
5289 break;
5293 /* Helper function to check dimensions. */
5294 static bool
5295 dim_ok (gfc_ss_info *info)
5297 int n;
5298 for (n = 0; n < info->dimen; n++)
5299 if (info->dim[n] != n)
5300 return false;
5301 return true;
5304 /* Convert an array for passing as an actual argument. Expressions and
5305 vector subscripts are evaluated and stored in a temporary, which is then
5306 passed. For whole arrays the descriptor is passed. For array sections
5307 a modified copy of the descriptor is passed, but using the original data.
5309 This function is also used for array pointer assignments, and there
5310 are three cases:
5312 - se->want_pointer && !se->direct_byref
5313 EXPR is an actual argument. On exit, se->expr contains a
5314 pointer to the array descriptor.
5316 - !se->want_pointer && !se->direct_byref
5317 EXPR is an actual argument to an intrinsic function or the
5318 left-hand side of a pointer assignment. On exit, se->expr
5319 contains the descriptor for EXPR.
5321 - !se->want_pointer && se->direct_byref
5322 EXPR is the right-hand side of a pointer assignment and
5323 se->expr is the descriptor for the previously-evaluated
5324 left-hand side. The function creates an assignment from
5325 EXPR to se->expr.
5328 The se->force_tmp flag disables the non-copying descriptor optimization
5329 that is used for transpose. It may be used in cases where there is an
5330 alias between the transpose argument and another argument in the same
5331 function call. */
5333 void
5334 gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
5336 gfc_loopinfo loop;
5337 gfc_ss_info *info;
5338 int need_tmp;
5339 int n;
5340 tree tmp;
5341 tree desc;
5342 stmtblock_t block;
5343 tree start;
5344 tree offset;
5345 int full;
5346 bool subref_array_target = false;
5347 gfc_expr *arg;
5349 gcc_assert (ss != NULL);
5350 gcc_assert (ss != gfc_ss_terminator);
5352 /* Special case things we know we can pass easily. */
5353 switch (expr->expr_type)
5355 case EXPR_VARIABLE:
5356 /* If we have a linear array section, we can pass it directly.
5357 Otherwise we need to copy it into a temporary. */
5359 gcc_assert (ss->type == GFC_SS_SECTION);
5360 gcc_assert (ss->expr == expr);
5361 info = &ss->data.info;
5363 /* Get the descriptor for the array. */
5364 gfc_conv_ss_descriptor (&se->pre, ss, 0);
5365 desc = info->descriptor;
5367 subref_array_target = se->direct_byref && is_subref_array (expr);
5368 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
5369 && !subref_array_target;
5371 if (se->force_tmp)
5372 need_tmp = 1;
5374 if (need_tmp)
5375 full = 0;
5376 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5378 /* Create a new descriptor if the array doesn't have one. */
5379 full = 0;
5381 else if (info->ref->u.ar.type == AR_FULL)
5382 full = 1;
5383 else if (se->direct_byref)
5384 full = 0;
5385 else
5386 full = gfc_full_array_ref_p (info->ref, NULL);
5388 if (full && dim_ok (info))
5390 if (se->direct_byref && !se->byref_noassign)
5392 /* Copy the descriptor for pointer assignments. */
5393 gfc_add_modify (&se->pre, se->expr, desc);
5395 /* Add any offsets from subreferences. */
5396 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
5397 subref_array_target, expr);
5399 else if (se->want_pointer)
5401 /* We pass full arrays directly. This means that pointers and
5402 allocatable arrays should also work. */
5403 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
5405 else
5407 se->expr = desc;
5410 if (expr->ts.type == BT_CHARACTER)
5411 se->string_length = gfc_get_expr_charlen (expr);
5413 return;
5415 break;
5417 case EXPR_FUNCTION:
5419 /* We don't need to copy data in some cases. */
5420 arg = gfc_get_noncopying_intrinsic_argument (expr);
5421 if (arg)
5423 /* This is a call to transpose... */
5424 gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE);
5425 /* ... which has already been handled by the scalarizer, so
5426 that we just need to get its argument's descriptor. */
5427 gfc_conv_expr_descriptor (se, expr->value.function.actual->expr, ss);
5428 return;
5431 /* A transformational function return value will be a temporary
5432 array descriptor. We still need to go through the scalarizer
5433 to create the descriptor. Elemental functions ar handled as
5434 arbitrary expressions, i.e. copy to a temporary. */
5436 if (se->direct_byref)
5438 gcc_assert (ss->type == GFC_SS_FUNCTION && ss->expr == expr);
5440 /* For pointer assignments pass the descriptor directly. */
5441 if (se->ss == NULL)
5442 se->ss = ss;
5443 else
5444 gcc_assert (se->ss == ss);
5445 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
5446 gfc_conv_expr (se, expr);
5447 return;
5450 if (ss->expr != expr || ss->type != GFC_SS_FUNCTION)
5452 if (ss->expr != expr)
5453 /* Elemental function. */
5454 gcc_assert ((expr->value.function.esym != NULL
5455 && expr->value.function.esym->attr.elemental)
5456 || (expr->value.function.isym != NULL
5457 && expr->value.function.isym->elemental));
5458 else
5459 gcc_assert (ss->type == GFC_SS_INTRINSIC);
5461 need_tmp = 1;
5462 if (expr->ts.type == BT_CHARACTER
5463 && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
5464 get_array_charlen (expr, se);
5466 info = NULL;
5468 else
5470 /* Transformational function. */
5471 info = &ss->data.info;
5472 need_tmp = 0;
5474 break;
5476 case EXPR_ARRAY:
5477 /* Constant array constructors don't need a temporary. */
5478 if (ss->type == GFC_SS_CONSTRUCTOR
5479 && expr->ts.type != BT_CHARACTER
5480 && gfc_constant_array_constructor_p (expr->value.constructor))
5482 need_tmp = 0;
5483 info = &ss->data.info;
5485 else
5487 need_tmp = 1;
5488 info = NULL;
5490 break;
5492 default:
5493 /* Something complicated. Copy it into a temporary. */
5494 need_tmp = 1;
5495 info = NULL;
5496 break;
5499 /* If we are creating a temporary, we don't need to bother about aliases
5500 anymore. */
5501 if (need_tmp)
5502 se->force_tmp = 0;
5504 gfc_init_loopinfo (&loop);
5506 /* Associate the SS with the loop. */
5507 gfc_add_ss_to_loop (&loop, ss);
5509 /* Tell the scalarizer not to bother creating loop variables, etc. */
5510 if (!need_tmp)
5511 loop.array_parameter = 1;
5512 else
5513 /* The right-hand side of a pointer assignment mustn't use a temporary. */
5514 gcc_assert (!se->direct_byref);
5516 /* Setup the scalarizing loops and bounds. */
5517 gfc_conv_ss_startstride (&loop);
5519 if (need_tmp)
5521 /* Tell the scalarizer to make a temporary. */
5522 loop.temp_ss = gfc_get_ss ();
5523 loop.temp_ss->type = GFC_SS_TEMP;
5524 loop.temp_ss->next = gfc_ss_terminator;
5526 if (expr->ts.type == BT_CHARACTER
5527 && !expr->ts.u.cl->backend_decl)
5528 get_array_charlen (expr, se);
5530 loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
5532 if (expr->ts.type == BT_CHARACTER)
5533 loop.temp_ss->string_length = expr->ts.u.cl->backend_decl;
5534 else
5535 loop.temp_ss->string_length = NULL;
5537 se->string_length = loop.temp_ss->string_length;
5538 loop.temp_ss->data.temp.dimen = loop.dimen;
5539 gfc_add_ss_to_loop (&loop, loop.temp_ss);
5542 gfc_conv_loop_setup (&loop, & expr->where);
5544 if (need_tmp)
5546 /* Copy into a temporary and pass that. We don't need to copy the data
5547 back because expressions and vector subscripts must be INTENT_IN. */
5548 /* TODO: Optimize passing function return values. */
5549 gfc_se lse;
5550 gfc_se rse;
5552 /* Start the copying loops. */
5553 gfc_mark_ss_chain_used (loop.temp_ss, 1);
5554 gfc_mark_ss_chain_used (ss, 1);
5555 gfc_start_scalarized_body (&loop, &block);
5557 /* Copy each data element. */
5558 gfc_init_se (&lse, NULL);
5559 gfc_copy_loopinfo_to_se (&lse, &loop);
5560 gfc_init_se (&rse, NULL);
5561 gfc_copy_loopinfo_to_se (&rse, &loop);
5563 lse.ss = loop.temp_ss;
5564 rse.ss = ss;
5566 gfc_conv_scalarized_array_ref (&lse, NULL);
5567 if (expr->ts.type == BT_CHARACTER)
5569 gfc_conv_expr (&rse, expr);
5570 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
5571 rse.expr = build_fold_indirect_ref_loc (input_location,
5572 rse.expr);
5574 else
5575 gfc_conv_expr_val (&rse, expr);
5577 gfc_add_block_to_block (&block, &rse.pre);
5578 gfc_add_block_to_block (&block, &lse.pre);
5580 lse.string_length = rse.string_length;
5581 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
5582 expr->expr_type == EXPR_VARIABLE, true);
5583 gfc_add_expr_to_block (&block, tmp);
5585 /* Finish the copying loops. */
5586 gfc_trans_scalarizing_loops (&loop, &block);
5588 desc = loop.temp_ss->data.info.descriptor;
5590 else if (expr->expr_type == EXPR_FUNCTION && dim_ok (info))
5592 desc = info->descriptor;
5593 se->string_length = ss->string_length;
5595 else
5597 /* We pass sections without copying to a temporary. Make a new
5598 descriptor and point it at the section we want. The loop variable
5599 limits will be the limits of the section.
5600 A function may decide to repack the array to speed up access, but
5601 we're not bothered about that here. */
5602 int dim, ndim;
5603 tree parm;
5604 tree parmtype;
5605 tree stride;
5606 tree from;
5607 tree to;
5608 tree base;
5610 /* Set the string_length for a character array. */
5611 if (expr->ts.type == BT_CHARACTER)
5612 se->string_length = gfc_get_expr_charlen (expr);
5614 desc = info->descriptor;
5615 if (se->direct_byref && !se->byref_noassign)
5617 /* For pointer assignments we fill in the destination. */
5618 parm = se->expr;
5619 parmtype = TREE_TYPE (parm);
5621 else
5623 /* Otherwise make a new one. */
5624 parmtype = gfc_get_element_type (TREE_TYPE (desc));
5625 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
5626 loop.from, loop.to, 0,
5627 GFC_ARRAY_UNKNOWN, false);
5628 parm = gfc_create_var (parmtype, "parm");
5631 offset = gfc_index_zero_node;
5633 /* The following can be somewhat confusing. We have two
5634 descriptors, a new one and the original array.
5635 {parm, parmtype, dim} refer to the new one.
5636 {desc, type, n, loop} refer to the original, which maybe
5637 a descriptorless array.
5638 The bounds of the scalarization are the bounds of the section.
5639 We don't have to worry about numeric overflows when calculating
5640 the offsets because all elements are within the array data. */
5642 /* Set the dtype. */
5643 tmp = gfc_conv_descriptor_dtype (parm);
5644 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
5646 /* Set offset for assignments to pointer only to zero if it is not
5647 the full array. */
5648 if (se->direct_byref
5649 && info->ref && info->ref->u.ar.type != AR_FULL)
5650 base = gfc_index_zero_node;
5651 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5652 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
5653 else
5654 base = NULL_TREE;
5656 ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
5657 for (n = 0; n < ndim; n++)
5659 stride = gfc_conv_array_stride (desc, n);
5661 /* Work out the offset. */
5662 if (info->ref
5663 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
5665 gcc_assert (info->subscript[n]
5666 && info->subscript[n]->type == GFC_SS_SCALAR);
5667 start = info->subscript[n]->data.scalar.expr;
5669 else
5671 /* Evaluate and remember the start of the section. */
5672 start = info->start[n];
5673 stride = gfc_evaluate_now (stride, &loop.pre);
5676 tmp = gfc_conv_array_lbound (desc, n);
5677 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (tmp),
5678 start, tmp);
5679 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
5680 tmp, stride);
5681 offset = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (tmp),
5682 offset, tmp);
5684 if (info->ref
5685 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
5687 /* For elemental dimensions, we only need the offset. */
5688 continue;
5691 /* Vector subscripts need copying and are handled elsewhere. */
5692 if (info->ref)
5693 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
5695 /* look for the corresponding scalarizer dimension: dim. */
5696 for (dim = 0; dim < ndim; dim++)
5697 if (info->dim[dim] == n)
5698 break;
5700 /* loop exited early: the DIM being looked for has been found. */
5701 gcc_assert (dim < ndim);
5703 /* Set the new lower bound. */
5704 from = loop.from[dim];
5705 to = loop.to[dim];
5707 /* If we have an array section or are assigning make sure that
5708 the lower bound is 1. References to the full
5709 array should otherwise keep the original bounds. */
5710 if ((!info->ref
5711 || info->ref->u.ar.type != AR_FULL)
5712 && !integer_onep (from))
5714 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5715 gfc_array_index_type, gfc_index_one_node,
5716 from);
5717 to = fold_build2_loc (input_location, PLUS_EXPR,
5718 gfc_array_index_type, to, tmp);
5719 from = gfc_index_one_node;
5721 gfc_conv_descriptor_lbound_set (&loop.pre, parm,
5722 gfc_rank_cst[dim], from);
5724 /* Set the new upper bound. */
5725 gfc_conv_descriptor_ubound_set (&loop.pre, parm,
5726 gfc_rank_cst[dim], to);
5728 /* Multiply the stride by the section stride to get the
5729 total stride. */
5730 stride = fold_build2_loc (input_location, MULT_EXPR,
5731 gfc_array_index_type,
5732 stride, info->stride[n]);
5734 if (se->direct_byref
5735 && info->ref
5736 && info->ref->u.ar.type != AR_FULL)
5738 base = fold_build2_loc (input_location, MINUS_EXPR,
5739 TREE_TYPE (base), base, stride);
5741 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5743 tmp = gfc_conv_array_lbound (desc, n);
5744 tmp = fold_build2_loc (input_location, MINUS_EXPR,
5745 TREE_TYPE (base), tmp, loop.from[dim]);
5746 tmp = fold_build2_loc (input_location, MULT_EXPR,
5747 TREE_TYPE (base), tmp,
5748 gfc_conv_array_stride (desc, n));
5749 base = fold_build2_loc (input_location, PLUS_EXPR,
5750 TREE_TYPE (base), tmp, base);
5753 /* Store the new stride. */
5754 gfc_conv_descriptor_stride_set (&loop.pre, parm,
5755 gfc_rank_cst[dim], stride);
5758 if (se->data_not_needed)
5759 gfc_conv_descriptor_data_set (&loop.pre, parm,
5760 gfc_index_zero_node);
5761 else
5762 /* Point the data pointer at the 1st element in the section. */
5763 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
5764 subref_array_target, expr);
5766 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5767 && !se->data_not_needed)
5769 /* Set the offset. */
5770 gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
5772 else
5774 /* Only the callee knows what the correct offset it, so just set
5775 it to zero here. */
5776 gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
5778 desc = parm;
5781 if (!se->direct_byref || se->byref_noassign)
5783 /* Get a pointer to the new descriptor. */
5784 if (se->want_pointer)
5785 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
5786 else
5787 se->expr = desc;
5790 gfc_add_block_to_block (&se->pre, &loop.pre);
5791 gfc_add_block_to_block (&se->post, &loop.post);
5793 /* Cleanup the scalarizer. */
5794 gfc_cleanup_loop (&loop);
5797 /* Helper function for gfc_conv_array_parameter if array size needs to be
5798 computed. */
5800 static void
5801 array_parameter_size (tree desc, gfc_expr *expr, tree *size)
5803 tree elem;
5804 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5805 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
5806 else if (expr->rank > 1)
5807 *size = build_call_expr_loc (input_location,
5808 gfor_fndecl_size0, 1,
5809 gfc_build_addr_expr (NULL, desc));
5810 else
5812 tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
5813 tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
5815 *size = fold_build2_loc (input_location, MINUS_EXPR,
5816 gfc_array_index_type, ubound, lbound);
5817 *size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5818 *size, gfc_index_one_node);
5819 *size = fold_build2_loc (input_location, MAX_EXPR, gfc_array_index_type,
5820 *size, gfc_index_zero_node);
5822 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
5823 *size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5824 *size, fold_convert (gfc_array_index_type, elem));
5827 /* Convert an array for passing as an actual parameter. */
5828 /* TODO: Optimize passing g77 arrays. */
5830 void
5831 gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
5832 const gfc_symbol *fsym, const char *proc_name,
5833 tree *size)
5835 tree ptr;
5836 tree desc;
5837 tree tmp = NULL_TREE;
5838 tree stmt;
5839 tree parent = DECL_CONTEXT (current_function_decl);
5840 bool full_array_var;
5841 bool this_array_result;
5842 bool contiguous;
5843 bool no_pack;
5844 bool array_constructor;
5845 bool good_allocatable;
5846 bool ultimate_ptr_comp;
5847 bool ultimate_alloc_comp;
5848 gfc_symbol *sym;
5849 stmtblock_t block;
5850 gfc_ref *ref;
5852 ultimate_ptr_comp = false;
5853 ultimate_alloc_comp = false;
5855 for (ref = expr->ref; ref; ref = ref->next)
5857 if (ref->next == NULL)
5858 break;
5860 if (ref->type == REF_COMPONENT)
5862 ultimate_ptr_comp = ref->u.c.component->attr.pointer;
5863 ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
5867 full_array_var = false;
5868 contiguous = false;
5870 if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
5871 full_array_var = gfc_full_array_ref_p (ref, &contiguous);
5873 sym = full_array_var ? expr->symtree->n.sym : NULL;
5875 /* The symbol should have an array specification. */
5876 gcc_assert (!sym || sym->as || ref->u.ar.as);
5878 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
5880 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
5881 expr->ts.u.cl->backend_decl = tmp;
5882 se->string_length = tmp;
5885 /* Is this the result of the enclosing procedure? */
5886 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
5887 if (this_array_result
5888 && (sym->backend_decl != current_function_decl)
5889 && (sym->backend_decl != parent))
5890 this_array_result = false;
5892 /* Passing address of the array if it is not pointer or assumed-shape. */
5893 if (full_array_var && g77 && !this_array_result)
5895 tmp = gfc_get_symbol_decl (sym);
5897 if (sym->ts.type == BT_CHARACTER)
5898 se->string_length = sym->ts.u.cl->backend_decl;
5900 if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)
5902 gfc_conv_expr_descriptor (se, expr, ss);
5903 se->expr = gfc_conv_array_data (se->expr);
5904 return;
5907 if (!sym->attr.pointer
5908 && sym->as
5909 && sym->as->type != AS_ASSUMED_SHAPE
5910 && !sym->attr.allocatable)
5912 /* Some variables are declared directly, others are declared as
5913 pointers and allocated on the heap. */
5914 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
5915 se->expr = tmp;
5916 else
5917 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
5918 if (size)
5919 array_parameter_size (tmp, expr, size);
5920 return;
5923 if (sym->attr.allocatable)
5925 if (sym->attr.dummy || sym->attr.result)
5927 gfc_conv_expr_descriptor (se, expr, ss);
5928 tmp = se->expr;
5930 if (size)
5931 array_parameter_size (tmp, expr, size);
5932 se->expr = gfc_conv_array_data (tmp);
5933 return;
5937 /* A convenient reduction in scope. */
5938 contiguous = g77 && !this_array_result && contiguous;
5940 /* There is no need to pack and unpack the array, if it is contiguous
5941 and not a deferred- or assumed-shape array, or if it is simply
5942 contiguous. */
5943 no_pack = ((sym && sym->as
5944 && !sym->attr.pointer
5945 && sym->as->type != AS_DEFERRED
5946 && sym->as->type != AS_ASSUMED_SHAPE)
5948 (ref && ref->u.ar.as
5949 && ref->u.ar.as->type != AS_DEFERRED
5950 && ref->u.ar.as->type != AS_ASSUMED_SHAPE)
5952 gfc_is_simply_contiguous (expr, false));
5954 no_pack = contiguous && no_pack;
5956 /* Array constructors are always contiguous and do not need packing. */
5957 array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
5959 /* Same is true of contiguous sections from allocatable variables. */
5960 good_allocatable = contiguous
5961 && expr->symtree
5962 && expr->symtree->n.sym->attr.allocatable;
5964 /* Or ultimate allocatable components. */
5965 ultimate_alloc_comp = contiguous && ultimate_alloc_comp;
5967 if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
5969 gfc_conv_expr_descriptor (se, expr, ss);
5970 if (expr->ts.type == BT_CHARACTER)
5971 se->string_length = expr->ts.u.cl->backend_decl;
5972 if (size)
5973 array_parameter_size (se->expr, expr, size);
5974 se->expr = gfc_conv_array_data (se->expr);
5975 return;
5978 if (this_array_result)
5980 /* Result of the enclosing function. */
5981 gfc_conv_expr_descriptor (se, expr, ss);
5982 if (size)
5983 array_parameter_size (se->expr, expr, size);
5984 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
5986 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
5987 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
5988 se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
5989 se->expr));
5991 return;
5993 else
5995 /* Every other type of array. */
5996 se->want_pointer = 1;
5997 gfc_conv_expr_descriptor (se, expr, ss);
5998 if (size)
5999 array_parameter_size (build_fold_indirect_ref_loc (input_location,
6000 se->expr),
6001 expr, size);
6004 /* Deallocate the allocatable components of structures that are
6005 not variable. */
6006 if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
6007 && expr->ts.u.derived->attr.alloc_comp
6008 && expr->expr_type != EXPR_VARIABLE)
6010 tmp = build_fold_indirect_ref_loc (input_location,
6011 se->expr);
6012 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
6013 gfc_add_expr_to_block (&se->post, tmp);
6016 if (g77 || (fsym && fsym->attr.contiguous
6017 && !gfc_is_simply_contiguous (expr, false)))
6019 tree origptr = NULL_TREE;
6021 desc = se->expr;
6023 /* For contiguous arrays, save the original value of the descriptor. */
6024 if (!g77)
6026 origptr = gfc_create_var (pvoid_type_node, "origptr");
6027 tmp = build_fold_indirect_ref_loc (input_location, desc);
6028 tmp = gfc_conv_array_data (tmp);
6029 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
6030 TREE_TYPE (origptr), origptr,
6031 fold_convert (TREE_TYPE (origptr), tmp));
6032 gfc_add_expr_to_block (&se->pre, tmp);
6035 /* Repack the array. */
6036 if (gfc_option.warn_array_temp)
6038 if (fsym)
6039 gfc_warning ("Creating array temporary at %L for argument '%s'",
6040 &expr->where, fsym->name);
6041 else
6042 gfc_warning ("Creating array temporary at %L", &expr->where);
6045 ptr = build_call_expr_loc (input_location,
6046 gfor_fndecl_in_pack, 1, desc);
6048 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
6050 tmp = gfc_conv_expr_present (sym);
6051 ptr = build3_loc (input_location, COND_EXPR, TREE_TYPE (se->expr),
6052 tmp, fold_convert (TREE_TYPE (se->expr), ptr),
6053 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
6056 ptr = gfc_evaluate_now (ptr, &se->pre);
6058 /* Use the packed data for the actual argument, except for contiguous arrays,
6059 where the descriptor's data component is set. */
6060 if (g77)
6061 se->expr = ptr;
6062 else
6064 tmp = build_fold_indirect_ref_loc (input_location, desc);
6065 gfc_conv_descriptor_data_set (&se->pre, tmp, ptr);
6068 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
6070 char * msg;
6072 if (fsym && proc_name)
6073 asprintf (&msg, "An array temporary was created for argument "
6074 "'%s' of procedure '%s'", fsym->name, proc_name);
6075 else
6076 asprintf (&msg, "An array temporary was created");
6078 tmp = build_fold_indirect_ref_loc (input_location,
6079 desc);
6080 tmp = gfc_conv_array_data (tmp);
6081 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6082 fold_convert (TREE_TYPE (tmp), ptr), tmp);
6084 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
6085 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6086 boolean_type_node,
6087 gfc_conv_expr_present (sym), tmp);
6089 gfc_trans_runtime_check (false, true, tmp, &se->pre,
6090 &expr->where, msg);
6091 gfc_free (msg);
6094 gfc_start_block (&block);
6096 /* Copy the data back. */
6097 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
6099 tmp = build_call_expr_loc (input_location,
6100 gfor_fndecl_in_unpack, 2, desc, ptr);
6101 gfc_add_expr_to_block (&block, tmp);
6104 /* Free the temporary. */
6105 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
6106 gfc_add_expr_to_block (&block, tmp);
6108 stmt = gfc_finish_block (&block);
6110 gfc_init_block (&block);
6111 /* Only if it was repacked. This code needs to be executed before the
6112 loop cleanup code. */
6113 tmp = build_fold_indirect_ref_loc (input_location,
6114 desc);
6115 tmp = gfc_conv_array_data (tmp);
6116 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6117 fold_convert (TREE_TYPE (tmp), ptr), tmp);
6119 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
6120 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6121 boolean_type_node,
6122 gfc_conv_expr_present (sym), tmp);
6124 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
6126 gfc_add_expr_to_block (&block, tmp);
6127 gfc_add_block_to_block (&block, &se->post);
6129 gfc_init_block (&se->post);
6131 /* Reset the descriptor pointer. */
6132 if (!g77)
6134 tmp = build_fold_indirect_ref_loc (input_location, desc);
6135 gfc_conv_descriptor_data_set (&se->post, tmp, origptr);
6138 gfc_add_block_to_block (&se->post, &block);
6143 /* Generate code to deallocate an array, if it is allocated. */
6145 tree
6146 gfc_trans_dealloc_allocated (tree descriptor)
6148 tree tmp;
6149 tree var;
6150 stmtblock_t block;
6152 gfc_start_block (&block);
6154 var = gfc_conv_descriptor_data_get (descriptor);
6155 STRIP_NOPS (var);
6157 /* Call array_deallocate with an int * present in the second argument.
6158 Although it is ignored here, it's presence ensures that arrays that
6159 are already deallocated are ignored. */
6160 tmp = gfc_deallocate_with_status (var, NULL_TREE, true, NULL);
6161 gfc_add_expr_to_block (&block, tmp);
6163 /* Zero the data pointer. */
6164 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6165 var, build_int_cst (TREE_TYPE (var), 0));
6166 gfc_add_expr_to_block (&block, tmp);
6168 return gfc_finish_block (&block);
6172 /* This helper function calculates the size in words of a full array. */
6174 static tree
6175 get_full_array_size (stmtblock_t *block, tree decl, int rank)
6177 tree idx;
6178 tree nelems;
6179 tree tmp;
6180 idx = gfc_rank_cst[rank - 1];
6181 nelems = gfc_conv_descriptor_ubound_get (decl, idx);
6182 tmp = gfc_conv_descriptor_lbound_get (decl, idx);
6183 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
6184 nelems, tmp);
6185 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
6186 tmp, gfc_index_one_node);
6187 tmp = gfc_evaluate_now (tmp, block);
6189 nelems = gfc_conv_descriptor_stride_get (decl, idx);
6190 tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6191 nelems, tmp);
6192 return gfc_evaluate_now (tmp, block);
6196 /* Allocate dest to the same size as src, and copy src -> dest.
6197 If no_malloc is set, only the copy is done. */
6199 static tree
6200 duplicate_allocatable (tree dest, tree src, tree type, int rank,
6201 bool no_malloc)
6203 tree tmp;
6204 tree size;
6205 tree nelems;
6206 tree null_cond;
6207 tree null_data;
6208 stmtblock_t block;
6210 /* If the source is null, set the destination to null. Then,
6211 allocate memory to the destination. */
6212 gfc_init_block (&block);
6214 if (rank == 0)
6216 tmp = null_pointer_node;
6217 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type, dest, tmp);
6218 gfc_add_expr_to_block (&block, tmp);
6219 null_data = gfc_finish_block (&block);
6221 gfc_init_block (&block);
6222 size = TYPE_SIZE_UNIT (TREE_TYPE (type));
6223 if (!no_malloc)
6225 tmp = gfc_call_malloc (&block, type, size);
6226 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6227 dest, fold_convert (type, tmp));
6228 gfc_add_expr_to_block (&block, tmp);
6231 tmp = built_in_decls[BUILT_IN_MEMCPY];
6232 tmp = build_call_expr_loc (input_location, tmp, 3,
6233 dest, src, size);
6235 else
6237 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
6238 null_data = gfc_finish_block (&block);
6240 gfc_init_block (&block);
6241 nelems = get_full_array_size (&block, src, rank);
6242 tmp = fold_convert (gfc_array_index_type,
6243 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
6244 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
6245 nelems, tmp);
6246 if (!no_malloc)
6248 tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
6249 tmp = gfc_call_malloc (&block, tmp, size);
6250 gfc_conv_descriptor_data_set (&block, dest, tmp);
6253 /* We know the temporary and the value will be the same length,
6254 so can use memcpy. */
6255 tmp = built_in_decls[BUILT_IN_MEMCPY];
6256 tmp = build_call_expr_loc (input_location,
6257 tmp, 3, gfc_conv_descriptor_data_get (dest),
6258 gfc_conv_descriptor_data_get (src), size);
6261 gfc_add_expr_to_block (&block, tmp);
6262 tmp = gfc_finish_block (&block);
6264 /* Null the destination if the source is null; otherwise do
6265 the allocate and copy. */
6266 if (rank == 0)
6267 null_cond = src;
6268 else
6269 null_cond = gfc_conv_descriptor_data_get (src);
6271 null_cond = convert (pvoid_type_node, null_cond);
6272 null_cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6273 null_cond, null_pointer_node);
6274 return build3_v (COND_EXPR, null_cond, tmp, null_data);
6278 /* Allocate dest to the same size as src, and copy data src -> dest. */
6280 tree
6281 gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank)
6283 return duplicate_allocatable (dest, src, type, rank, false);
6287 /* Copy data src -> dest. */
6289 tree
6290 gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
6292 return duplicate_allocatable (dest, src, type, rank, true);
6296 /* Recursively traverse an object of derived type, generating code to
6297 deallocate, nullify or copy allocatable components. This is the work horse
6298 function for the functions named in this enum. */
6300 enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP,
6301 COPY_ONLY_ALLOC_COMP};
6303 static tree
6304 structure_alloc_comps (gfc_symbol * der_type, tree decl,
6305 tree dest, int rank, int purpose)
6307 gfc_component *c;
6308 gfc_loopinfo loop;
6309 stmtblock_t fnblock;
6310 stmtblock_t loopbody;
6311 tree decl_type;
6312 tree tmp;
6313 tree comp;
6314 tree dcmp;
6315 tree nelems;
6316 tree index;
6317 tree var;
6318 tree cdecl;
6319 tree ctype;
6320 tree vref, dref;
6321 tree null_cond = NULL_TREE;
6323 gfc_init_block (&fnblock);
6325 decl_type = TREE_TYPE (decl);
6327 if ((POINTER_TYPE_P (decl_type) && rank != 0)
6328 || (TREE_CODE (decl_type) == REFERENCE_TYPE && rank == 0))
6330 decl = build_fold_indirect_ref_loc (input_location,
6331 decl);
6333 /* Just in case in gets dereferenced. */
6334 decl_type = TREE_TYPE (decl);
6336 /* If this an array of derived types with allocatable components
6337 build a loop and recursively call this function. */
6338 if (TREE_CODE (decl_type) == ARRAY_TYPE
6339 || GFC_DESCRIPTOR_TYPE_P (decl_type))
6341 tmp = gfc_conv_array_data (decl);
6342 var = build_fold_indirect_ref_loc (input_location,
6343 tmp);
6345 /* Get the number of elements - 1 and set the counter. */
6346 if (GFC_DESCRIPTOR_TYPE_P (decl_type))
6348 /* Use the descriptor for an allocatable array. Since this
6349 is a full array reference, we only need the descriptor
6350 information from dimension = rank. */
6351 tmp = get_full_array_size (&fnblock, decl, rank);
6352 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6353 gfc_array_index_type, tmp,
6354 gfc_index_one_node);
6356 null_cond = gfc_conv_descriptor_data_get (decl);
6357 null_cond = fold_build2_loc (input_location, NE_EXPR,
6358 boolean_type_node, null_cond,
6359 build_int_cst (TREE_TYPE (null_cond), 0));
6361 else
6363 /* Otherwise use the TYPE_DOMAIN information. */
6364 tmp = array_type_nelts (decl_type);
6365 tmp = fold_convert (gfc_array_index_type, tmp);
6368 /* Remember that this is, in fact, the no. of elements - 1. */
6369 nelems = gfc_evaluate_now (tmp, &fnblock);
6370 index = gfc_create_var (gfc_array_index_type, "S");
6372 /* Build the body of the loop. */
6373 gfc_init_block (&loopbody);
6375 vref = gfc_build_array_ref (var, index, NULL);
6377 if (purpose == COPY_ALLOC_COMP)
6379 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
6381 tmp = gfc_duplicate_allocatable (dest, decl, decl_type, rank);
6382 gfc_add_expr_to_block (&fnblock, tmp);
6384 tmp = build_fold_indirect_ref_loc (input_location,
6385 gfc_conv_array_data (dest));
6386 dref = gfc_build_array_ref (tmp, index, NULL);
6387 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
6389 else if (purpose == COPY_ONLY_ALLOC_COMP)
6391 tmp = build_fold_indirect_ref_loc (input_location,
6392 gfc_conv_array_data (dest));
6393 dref = gfc_build_array_ref (tmp, index, NULL);
6394 tmp = structure_alloc_comps (der_type, vref, dref, rank,
6395 COPY_ALLOC_COMP);
6397 else
6398 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
6400 gfc_add_expr_to_block (&loopbody, tmp);
6402 /* Build the loop and return. */
6403 gfc_init_loopinfo (&loop);
6404 loop.dimen = 1;
6405 loop.from[0] = gfc_index_zero_node;
6406 loop.loopvar[0] = index;
6407 loop.to[0] = nelems;
6408 gfc_trans_scalarizing_loops (&loop, &loopbody);
6409 gfc_add_block_to_block (&fnblock, &loop.pre);
6411 tmp = gfc_finish_block (&fnblock);
6412 if (null_cond != NULL_TREE)
6413 tmp = build3_v (COND_EXPR, null_cond, tmp,
6414 build_empty_stmt (input_location));
6416 return tmp;
6419 /* Otherwise, act on the components or recursively call self to
6420 act on a chain of components. */
6421 for (c = der_type->components; c; c = c->next)
6423 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED
6424 || c->ts.type == BT_CLASS)
6425 && c->ts.u.derived->attr.alloc_comp;
6426 cdecl = c->backend_decl;
6427 ctype = TREE_TYPE (cdecl);
6429 switch (purpose)
6431 case DEALLOCATE_ALLOC_COMP:
6432 if (c->attr.allocatable && c->attr.dimension)
6434 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
6435 decl, cdecl, NULL_TREE);
6436 if (cmp_has_alloc_comps && !c->attr.pointer)
6438 /* Do not deallocate the components of ultimate pointer
6439 components. */
6440 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
6441 c->as->rank, purpose);
6442 gfc_add_expr_to_block (&fnblock, tmp);
6444 tmp = gfc_trans_dealloc_allocated (comp);
6445 gfc_add_expr_to_block (&fnblock, tmp);
6447 else if (c->attr.allocatable)
6449 /* Allocatable scalar components. */
6450 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
6451 decl, cdecl, NULL_TREE);
6453 tmp = gfc_deallocate_scalar_with_status (comp, NULL, true, NULL,
6454 c->ts);
6455 gfc_add_expr_to_block (&fnblock, tmp);
6457 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
6458 void_type_node, comp,
6459 build_int_cst (TREE_TYPE (comp), 0));
6460 gfc_add_expr_to_block (&fnblock, tmp);
6462 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
6464 /* Allocatable scalar CLASS components. */
6465 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
6466 decl, cdecl, NULL_TREE);
6468 /* Add reference to '_data' component. */
6469 tmp = CLASS_DATA (c)->backend_decl;
6470 comp = fold_build3_loc (input_location, COMPONENT_REF,
6471 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
6473 tmp = gfc_deallocate_scalar_with_status (comp, NULL, true, NULL,
6474 CLASS_DATA (c)->ts);
6475 gfc_add_expr_to_block (&fnblock, tmp);
6477 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
6478 void_type_node, comp,
6479 build_int_cst (TREE_TYPE (comp), 0));
6480 gfc_add_expr_to_block (&fnblock, tmp);
6482 break;
6484 case NULLIFY_ALLOC_COMP:
6485 if (c->attr.pointer)
6486 continue;
6487 else if (c->attr.allocatable && c->attr.dimension)
6489 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
6490 decl, cdecl, NULL_TREE);
6491 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
6493 else if (c->attr.allocatable)
6495 /* Allocatable scalar components. */
6496 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
6497 decl, cdecl, NULL_TREE);
6498 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
6499 void_type_node, comp,
6500 build_int_cst (TREE_TYPE (comp), 0));
6501 gfc_add_expr_to_block (&fnblock, tmp);
6503 else if (c->ts.type == BT_CLASS && CLASS_DATA (c)->attr.allocatable)
6505 /* Allocatable scalar CLASS components. */
6506 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
6507 decl, cdecl, NULL_TREE);
6508 /* Add reference to '_data' component. */
6509 tmp = CLASS_DATA (c)->backend_decl;
6510 comp = fold_build3_loc (input_location, COMPONENT_REF,
6511 TREE_TYPE (tmp), comp, tmp, NULL_TREE);
6512 tmp = fold_build2_loc (input_location, MODIFY_EXPR,
6513 void_type_node, comp,
6514 build_int_cst (TREE_TYPE (comp), 0));
6515 gfc_add_expr_to_block (&fnblock, tmp);
6517 else if (cmp_has_alloc_comps)
6519 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
6520 decl, cdecl, NULL_TREE);
6521 rank = c->as ? c->as->rank : 0;
6522 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
6523 rank, purpose);
6524 gfc_add_expr_to_block (&fnblock, tmp);
6526 break;
6528 case COPY_ALLOC_COMP:
6529 if (c->attr.pointer)
6530 continue;
6532 /* We need source and destination components. */
6533 comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl,
6534 cdecl, NULL_TREE);
6535 dcmp = fold_build3_loc (input_location, COMPONENT_REF, ctype, dest,
6536 cdecl, NULL_TREE);
6537 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
6539 if (c->attr.allocatable && !cmp_has_alloc_comps)
6541 rank = c->as ? c->as->rank : 0;
6542 tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank);
6543 gfc_add_expr_to_block (&fnblock, tmp);
6546 if (cmp_has_alloc_comps)
6548 rank = c->as ? c->as->rank : 0;
6549 tmp = fold_convert (TREE_TYPE (dcmp), comp);
6550 gfc_add_modify (&fnblock, dcmp, tmp);
6551 tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
6552 rank, purpose);
6553 gfc_add_expr_to_block (&fnblock, tmp);
6555 break;
6557 default:
6558 gcc_unreachable ();
6559 break;
6563 return gfc_finish_block (&fnblock);
6566 /* Recursively traverse an object of derived type, generating code to
6567 nullify allocatable components. */
6569 tree
6570 gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
6572 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
6573 NULLIFY_ALLOC_COMP);
6577 /* Recursively traverse an object of derived type, generating code to
6578 deallocate allocatable components. */
6580 tree
6581 gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
6583 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
6584 DEALLOCATE_ALLOC_COMP);
6588 /* Recursively traverse an object of derived type, generating code to
6589 copy it and its allocatable components. */
6591 tree
6592 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
6594 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
6598 /* Recursively traverse an object of derived type, generating code to
6599 copy only its allocatable components. */
6601 tree
6602 gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
6604 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ONLY_ALLOC_COMP);
6608 /* Returns the value of LBOUND for an expression. This could be broken out
6609 from gfc_conv_intrinsic_bound but this seemed to be simpler. This is
6610 called by gfc_alloc_allocatable_for_assignment. */
6611 static tree
6612 get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
6614 tree lbound;
6615 tree ubound;
6616 tree stride;
6617 tree cond, cond1, cond3, cond4;
6618 tree tmp;
6619 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
6621 tmp = gfc_rank_cst[dim];
6622 lbound = gfc_conv_descriptor_lbound_get (desc, tmp);
6623 ubound = gfc_conv_descriptor_ubound_get (desc, tmp);
6624 stride = gfc_conv_descriptor_stride_get (desc, tmp);
6625 cond1 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
6626 ubound, lbound);
6627 cond3 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
6628 stride, gfc_index_zero_node);
6629 cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
6630 boolean_type_node, cond3, cond1);
6631 cond4 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
6632 stride, gfc_index_zero_node);
6633 if (assumed_size)
6634 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6635 tmp, build_int_cst (gfc_array_index_type,
6636 expr->rank - 1));
6637 else
6638 cond = boolean_false_node;
6640 cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR,
6641 boolean_type_node, cond3, cond4);
6642 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
6643 boolean_type_node, cond, cond1);
6645 return fold_build3_loc (input_location, COND_EXPR,
6646 gfc_array_index_type, cond,
6647 lbound, gfc_index_one_node);
6649 else if (expr->expr_type == EXPR_VARIABLE)
6651 tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
6652 return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
6654 else if (expr->expr_type == EXPR_FUNCTION)
6656 /* A conversion function, so use the argument. */
6657 expr = expr->value.function.actual->expr;
6658 if (expr->expr_type != EXPR_VARIABLE)
6659 return gfc_index_one_node;
6660 desc = TREE_TYPE (expr->symtree->n.sym->backend_decl);
6661 return get_std_lbound (expr, desc, dim, assumed_size);
6664 return gfc_index_one_node;
6668 /* Returns true if an expression represents an lhs that can be reallocated
6669 on assignment. */
6671 bool
6672 gfc_is_reallocatable_lhs (gfc_expr *expr)
6674 gfc_ref * ref;
6676 if (!expr->ref)
6677 return false;
6679 /* An allocatable variable. */
6680 if (expr->symtree->n.sym->attr.allocatable
6681 && expr->ref
6682 && expr->ref->type == REF_ARRAY
6683 && expr->ref->u.ar.type == AR_FULL)
6684 return true;
6686 /* All that can be left are allocatable components. */
6687 if ((expr->symtree->n.sym->ts.type != BT_DERIVED
6688 && expr->symtree->n.sym->ts.type != BT_CLASS)
6689 || !expr->symtree->n.sym->ts.u.derived->attr.alloc_comp)
6690 return false;
6692 /* Find a component ref followed by an array reference. */
6693 for (ref = expr->ref; ref; ref = ref->next)
6694 if (ref->next
6695 && ref->type == REF_COMPONENT
6696 && ref->next->type == REF_ARRAY
6697 && !ref->next->next)
6698 break;
6700 if (!ref)
6701 return false;
6703 /* Return true if valid reallocatable lhs. */
6704 if (ref->u.c.component->attr.allocatable
6705 && ref->next->u.ar.type == AR_FULL)
6706 return true;
6708 return false;
6712 /* Allocate the lhs of an assignment to an allocatable array, otherwise
6713 reallocate it. */
6715 tree
6716 gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
6717 gfc_expr *expr1,
6718 gfc_expr *expr2)
6720 stmtblock_t realloc_block;
6721 stmtblock_t alloc_block;
6722 stmtblock_t fblock;
6723 gfc_ss *rss;
6724 gfc_ss *lss;
6725 tree realloc_expr;
6726 tree alloc_expr;
6727 tree size1;
6728 tree size2;
6729 tree array1;
6730 tree cond;
6731 tree tmp;
6732 tree tmp2;
6733 tree lbound;
6734 tree ubound;
6735 tree desc;
6736 tree desc2;
6737 tree offset;
6738 tree jump_label1;
6739 tree jump_label2;
6740 tree neq_size;
6741 tree lbd;
6742 int n;
6743 int dim;
6744 gfc_array_spec * as;
6746 /* x = f(...) with x allocatable. In this case, expr1 is the rhs.
6747 Find the lhs expression in the loop chain and set expr1 and
6748 expr2 accordingly. */
6749 if (expr1->expr_type == EXPR_FUNCTION && expr2 == NULL)
6751 expr2 = expr1;
6752 /* Find the ss for the lhs. */
6753 lss = loop->ss;
6754 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
6755 if (lss->expr && lss->expr->expr_type == EXPR_VARIABLE)
6756 break;
6757 if (lss == gfc_ss_terminator)
6758 return NULL_TREE;
6759 expr1 = lss->expr;
6762 /* Bail out if this is not a valid allocate on assignment. */
6763 if (!gfc_is_reallocatable_lhs (expr1)
6764 || (expr2 && !expr2->rank))
6765 return NULL_TREE;
6767 /* Find the ss for the lhs. */
6768 lss = loop->ss;
6769 for (; lss && lss != gfc_ss_terminator; lss = lss->loop_chain)
6770 if (lss->expr == expr1)
6771 break;
6773 if (lss == gfc_ss_terminator)
6774 return NULL_TREE;
6776 /* Find an ss for the rhs. For operator expressions, we see the
6777 ss's for the operands. Any one of these will do. */
6778 rss = loop->ss;
6779 for (; rss && rss != gfc_ss_terminator; rss = rss->loop_chain)
6780 if (rss->expr != expr1 && rss != loop->temp_ss)
6781 break;
6783 if (expr2 && rss == gfc_ss_terminator)
6784 return NULL_TREE;
6786 gfc_start_block (&fblock);
6788 /* Since the lhs is allocatable, this must be a descriptor type.
6789 Get the data and array size. */
6790 desc = lss->data.info.descriptor;
6791 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
6792 array1 = gfc_conv_descriptor_data_get (desc);
6793 size1 = gfc_conv_descriptor_size (desc, expr1->rank);
6795 /* Get the rhs size. Fix both sizes. */
6796 if (expr2)
6797 desc2 = rss->data.info.descriptor;
6798 else
6799 desc2 = NULL_TREE;
6800 size2 = gfc_index_one_node;
6801 for (n = 0; n < expr2->rank; n++)
6803 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6804 gfc_array_index_type,
6805 loop->to[n], loop->from[n]);
6806 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6807 gfc_array_index_type,
6808 tmp, gfc_index_one_node);
6809 size2 = fold_build2_loc (input_location, MULT_EXPR,
6810 gfc_array_index_type,
6811 tmp, size2);
6813 size1 = gfc_evaluate_now (size1, &fblock);
6814 size2 = gfc_evaluate_now (size2, &fblock);
6815 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6816 size1, size2);
6817 neq_size = gfc_evaluate_now (cond, &fblock);
6819 /* If the lhs is allocated and the lhs and rhs are equal length, jump
6820 past the realloc/malloc. This allows F95 compliant expressions
6821 to escape allocation on assignment. */
6822 jump_label1 = gfc_build_label_decl (NULL_TREE);
6823 jump_label2 = gfc_build_label_decl (NULL_TREE);
6825 /* Allocate if data is NULL. */
6826 cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
6827 array1, build_int_cst (TREE_TYPE (array1), 0));
6828 tmp = build3_v (COND_EXPR, cond,
6829 build1_v (GOTO_EXPR, jump_label1),
6830 build_empty_stmt (input_location));
6831 gfc_add_expr_to_block (&fblock, tmp);
6833 /* Reallocate if sizes are different. */
6834 tmp = build3_v (COND_EXPR, neq_size,
6835 build1_v (GOTO_EXPR, jump_label1),
6836 build_empty_stmt (input_location));
6837 gfc_add_expr_to_block (&fblock, tmp);
6839 if (expr2 && expr2->expr_type == EXPR_FUNCTION
6840 && expr2->value.function.isym
6841 && expr2->value.function.isym->conversion)
6843 /* For conversion functions, take the arg. */
6844 gfc_expr *arg = expr2->value.function.actual->expr;
6845 as = gfc_get_full_arrayspec_from_expr (arg);
6847 else if (expr2)
6848 as = gfc_get_full_arrayspec_from_expr (expr2);
6849 else
6850 as = NULL;
6852 /* Reset the lhs bounds if any are different from the rhs. */
6853 if (as && expr2->expr_type == EXPR_VARIABLE)
6855 for (n = 0; n < expr1->rank; n++)
6857 /* First check the lbounds. */
6858 dim = rss->data.info.dim[n];
6859 lbd = get_std_lbound (expr2, desc2, dim,
6860 as->type == AS_ASSUMED_SIZE);
6861 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
6862 cond = fold_build2_loc (input_location, NE_EXPR,
6863 boolean_type_node, lbd, lbound);
6864 tmp = build3_v (COND_EXPR, cond,
6865 build1_v (GOTO_EXPR, jump_label1),
6866 build_empty_stmt (input_location));
6867 gfc_add_expr_to_block (&fblock, tmp);
6869 /* Now check the shape. */
6870 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6871 gfc_array_index_type,
6872 loop->to[n], loop->from[n]);
6873 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6874 gfc_array_index_type,
6875 tmp, lbound);
6876 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]);
6877 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6878 gfc_array_index_type,
6879 tmp, ubound);
6880 cond = fold_build2_loc (input_location, NE_EXPR,
6881 boolean_type_node,
6882 tmp, gfc_index_zero_node);
6883 tmp = build3_v (COND_EXPR, cond,
6884 build1_v (GOTO_EXPR, jump_label1),
6885 build_empty_stmt (input_location));
6886 gfc_add_expr_to_block (&fblock, tmp);
6890 /* Otherwise jump past the (re)alloc code. */
6891 tmp = build1_v (GOTO_EXPR, jump_label2);
6892 gfc_add_expr_to_block (&fblock, tmp);
6894 /* Add the label to start automatic (re)allocation. */
6895 tmp = build1_v (LABEL_EXPR, jump_label1);
6896 gfc_add_expr_to_block (&fblock, tmp);
6898 /* Now modify the lhs descriptor and the associated scalarizer
6899 variables.
6900 7.4.1.3: If variable is or becomes an unallocated allocatable
6901 variable, then it is allocated with each deferred type parameter
6902 equal to the corresponding type parameters of expr , with the
6903 shape of expr , and with each lower bound equal to the
6904 corresponding element of LBOUND(expr). */
6905 size1 = gfc_index_one_node;
6906 offset = gfc_index_zero_node;
6908 for (n = 0; n < expr2->rank; n++)
6910 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6911 gfc_array_index_type,
6912 loop->to[n], loop->from[n]);
6913 tmp = fold_build2_loc (input_location, PLUS_EXPR,
6914 gfc_array_index_type,
6915 tmp, gfc_index_one_node);
6917 lbound = gfc_index_one_node;
6918 ubound = tmp;
6920 if (as)
6922 lbd = get_std_lbound (expr2, desc2, n,
6923 as->type == AS_ASSUMED_SIZE);
6924 ubound = fold_build2_loc (input_location,
6925 MINUS_EXPR,
6926 gfc_array_index_type,
6927 ubound, lbound);
6928 ubound = fold_build2_loc (input_location,
6929 PLUS_EXPR,
6930 gfc_array_index_type,
6931 ubound, lbd);
6932 lbound = lbd;
6935 gfc_conv_descriptor_lbound_set (&fblock, desc,
6936 gfc_rank_cst[n],
6937 lbound);
6938 gfc_conv_descriptor_ubound_set (&fblock, desc,
6939 gfc_rank_cst[n],
6940 ubound);
6941 gfc_conv_descriptor_stride_set (&fblock, desc,
6942 gfc_rank_cst[n],
6943 size1);
6944 lbound = gfc_conv_descriptor_lbound_get (desc,
6945 gfc_rank_cst[n]);
6946 tmp2 = fold_build2_loc (input_location, MULT_EXPR,
6947 gfc_array_index_type,
6948 lbound, size1);
6949 offset = fold_build2_loc (input_location, MINUS_EXPR,
6950 gfc_array_index_type,
6951 offset, tmp2);
6952 size1 = fold_build2_loc (input_location, MULT_EXPR,
6953 gfc_array_index_type,
6954 tmp, size1);
6957 /* Set the lhs descriptor and scalarizer offsets. For rank > 1,
6958 the array offset is saved and the info.offset is used for a
6959 running offset. Use the saved_offset instead. */
6960 tmp = gfc_conv_descriptor_offset (desc);
6961 gfc_add_modify (&fblock, tmp, offset);
6962 if (lss->data.info.saved_offset
6963 && TREE_CODE (lss->data.info.saved_offset) == VAR_DECL)
6964 gfc_add_modify (&fblock, lss->data.info.saved_offset, tmp);
6966 /* Now set the deltas for the lhs. */
6967 for (n = 0; n < expr1->rank; n++)
6969 tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
6970 dim = lss->data.info.dim[n];
6971 tmp = fold_build2_loc (input_location, MINUS_EXPR,
6972 gfc_array_index_type, tmp,
6973 loop->from[dim]);
6974 if (lss->data.info.delta[dim]
6975 && TREE_CODE (lss->data.info.delta[dim]) == VAR_DECL)
6976 gfc_add_modify (&fblock, lss->data.info.delta[dim], tmp);
6979 /* Get the new lhs size in bytes. */
6980 if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
6982 tmp = expr2->ts.u.cl->backend_decl;
6983 gcc_assert (expr1->ts.u.cl->backend_decl);
6984 tmp = fold_convert (TREE_TYPE (expr1->ts.u.cl->backend_decl), tmp);
6985 gfc_add_modify (&fblock, expr1->ts.u.cl->backend_decl, tmp);
6987 else if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->backend_decl)
6989 tmp = TYPE_SIZE_UNIT (TREE_TYPE (gfc_typenode_for_spec (&expr1->ts)));
6990 tmp = fold_build2_loc (input_location, MULT_EXPR,
6991 gfc_array_index_type, tmp,
6992 expr1->ts.u.cl->backend_decl);
6994 else
6995 tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
6996 tmp = fold_convert (gfc_array_index_type, tmp);
6997 size2 = fold_build2_loc (input_location, MULT_EXPR,
6998 gfc_array_index_type,
6999 tmp, size2);
7000 size2 = fold_convert (size_type_node, size2);
7001 size2 = gfc_evaluate_now (size2, &fblock);
7003 /* Realloc expression. Note that the scalarizer uses desc.data
7004 in the array reference - (*desc.data)[<element>]. */
7005 gfc_init_block (&realloc_block);
7006 tmp = build_call_expr_loc (input_location,
7007 built_in_decls[BUILT_IN_REALLOC], 2,
7008 fold_convert (pvoid_type_node, array1),
7009 size2);
7010 gfc_conv_descriptor_data_set (&realloc_block,
7011 desc, tmp);
7012 realloc_expr = gfc_finish_block (&realloc_block);
7014 /* Only reallocate if sizes are different. */
7015 tmp = build3_v (COND_EXPR, neq_size, realloc_expr,
7016 build_empty_stmt (input_location));
7017 realloc_expr = tmp;
7020 /* Malloc expression. */
7021 gfc_init_block (&alloc_block);
7022 tmp = build_call_expr_loc (input_location,
7023 built_in_decls[BUILT_IN_MALLOC], 1,
7024 size2);
7025 gfc_conv_descriptor_data_set (&alloc_block,
7026 desc, tmp);
7027 tmp = gfc_conv_descriptor_dtype (desc);
7028 gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
7029 alloc_expr = gfc_finish_block (&alloc_block);
7031 /* Malloc if not allocated; realloc otherwise. */
7032 tmp = build_int_cst (TREE_TYPE (array1), 0);
7033 cond = fold_build2_loc (input_location, EQ_EXPR,
7034 boolean_type_node,
7035 array1, tmp);
7036 tmp = build3_v (COND_EXPR, cond, alloc_expr, realloc_expr);
7037 gfc_add_expr_to_block (&fblock, tmp);
7039 /* Make sure that the scalarizer data pointer is updated. */
7040 if (lss->data.info.data
7041 && TREE_CODE (lss->data.info.data) == VAR_DECL)
7043 tmp = gfc_conv_descriptor_data_get (desc);
7044 gfc_add_modify (&fblock, lss->data.info.data, tmp);
7047 /* Add the exit label. */
7048 tmp = build1_v (LABEL_EXPR, jump_label2);
7049 gfc_add_expr_to_block (&fblock, tmp);
7051 return gfc_finish_block (&fblock);
7055 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
7056 Do likewise, recursively if necessary, with the allocatable components of
7057 derived types. */
7059 void
7060 gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
7062 tree type;
7063 tree tmp;
7064 tree descriptor;
7065 stmtblock_t init;
7066 stmtblock_t cleanup;
7067 locus loc;
7068 int rank;
7069 bool sym_has_alloc_comp;
7071 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED
7072 || sym->ts.type == BT_CLASS)
7073 && sym->ts.u.derived->attr.alloc_comp;
7075 /* Make sure the frontend gets these right. */
7076 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
7077 fatal_error ("Possible front-end bug: Deferred array size without pointer, "
7078 "allocatable attribute or derived type without allocatable "
7079 "components.");
7081 gfc_init_block (&init);
7083 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
7084 || TREE_CODE (sym->backend_decl) == PARM_DECL);
7086 if (sym->ts.type == BT_CHARACTER
7087 && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
7089 gfc_conv_string_length (sym->ts.u.cl, NULL, &init);
7090 gfc_trans_vla_type_sizes (sym, &init);
7093 /* Dummy, use associated and result variables don't need anything special. */
7094 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
7096 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
7097 return;
7100 gfc_save_backend_locus (&loc);
7101 gfc_set_backend_locus (&sym->declared_at);
7102 descriptor = sym->backend_decl;
7104 /* Although static, derived types with default initializers and
7105 allocatable components must not be nulled wholesale; instead they
7106 are treated component by component. */
7107 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
7109 /* SAVEd variables are not freed on exit. */
7110 gfc_trans_static_array_pointer (sym);
7112 gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
7113 gfc_restore_backend_locus (&loc);
7114 return;
7117 /* Get the descriptor type. */
7118 type = TREE_TYPE (sym->backend_decl);
7120 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
7122 if (!sym->attr.save
7123 && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
7125 if (sym->value == NULL
7126 || !gfc_has_default_initializer (sym->ts.u.derived))
7128 rank = sym->as ? sym->as->rank : 0;
7129 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived,
7130 descriptor, rank);
7131 gfc_add_expr_to_block (&init, tmp);
7133 else
7134 gfc_init_default_dt (sym, &init, false);
7137 else if (!GFC_DESCRIPTOR_TYPE_P (type))
7139 /* If the backend_decl is not a descriptor, we must have a pointer
7140 to one. */
7141 descriptor = build_fold_indirect_ref_loc (input_location,
7142 sym->backend_decl);
7143 type = TREE_TYPE (descriptor);
7146 /* NULLIFY the data pointer. */
7147 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
7148 gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
7150 gfc_init_block (&cleanup);
7151 gfc_restore_backend_locus (&loc);
7153 /* Allocatable arrays need to be freed when they go out of scope.
7154 The allocatable components of pointers must not be touched. */
7155 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
7156 && !sym->attr.pointer && !sym->attr.save)
7158 int rank;
7159 rank = sym->as ? sym->as->rank : 0;
7160 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
7161 gfc_add_expr_to_block (&cleanup, tmp);
7164 if (sym->attr.allocatable && sym->attr.dimension
7165 && !sym->attr.save && !sym->attr.result)
7167 tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
7168 gfc_add_expr_to_block (&cleanup, tmp);
7171 gfc_add_init_cleanup (block, gfc_finish_block (&init),
7172 gfc_finish_block (&cleanup));
7175 /************ Expression Walking Functions ******************/
7177 /* Walk a variable reference.
7179 Possible extension - multiple component subscripts.
7180 x(:,:) = foo%a(:)%b(:)
7181 Transforms to
7182 forall (i=..., j=...)
7183 x(i,j) = foo%a(j)%b(i)
7184 end forall
7185 This adds a fair amount of complexity because you need to deal with more
7186 than one ref. Maybe handle in a similar manner to vector subscripts.
7187 Maybe not worth the effort. */
7190 static gfc_ss *
7191 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
7193 gfc_ref *ref;
7194 gfc_array_ref *ar;
7195 gfc_ss *newss;
7196 int n;
7198 for (ref = expr->ref; ref; ref = ref->next)
7199 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
7200 break;
7202 for (; ref; ref = ref->next)
7204 if (ref->type == REF_SUBSTRING)
7206 newss = gfc_get_ss ();
7207 newss->type = GFC_SS_SCALAR;
7208 newss->expr = ref->u.ss.start;
7209 newss->next = ss;
7210 ss = newss;
7212 newss = gfc_get_ss ();
7213 newss->type = GFC_SS_SCALAR;
7214 newss->expr = ref->u.ss.end;
7215 newss->next = ss;
7216 ss = newss;
7219 /* We're only interested in array sections from now on. */
7220 if (ref->type != REF_ARRAY)
7221 continue;
7223 ar = &ref->u.ar;
7225 if (ar->as->rank == 0)
7227 /* Scalar coarray. */
7228 continue;
7231 switch (ar->type)
7233 case AR_ELEMENT:
7234 for (n = 0; n < ar->dimen; n++)
7236 newss = gfc_get_ss ();
7237 newss->type = GFC_SS_SCALAR;
7238 newss->expr = ar->start[n];
7239 newss->next = ss;
7240 ss = newss;
7242 break;
7244 case AR_FULL:
7245 newss = gfc_get_ss ();
7246 newss->type = GFC_SS_SECTION;
7247 newss->expr = expr;
7248 newss->next = ss;
7249 newss->data.info.dimen = ar->as->rank;
7250 newss->data.info.ref = ref;
7252 /* Make sure array is the same as array(:,:), this way
7253 we don't need to special case all the time. */
7254 ar->dimen = ar->as->rank;
7255 for (n = 0; n < ar->dimen; n++)
7257 newss->data.info.dim[n] = n;
7258 ar->dimen_type[n] = DIMEN_RANGE;
7260 gcc_assert (ar->start[n] == NULL);
7261 gcc_assert (ar->end[n] == NULL);
7262 gcc_assert (ar->stride[n] == NULL);
7264 ss = newss;
7265 break;
7267 case AR_SECTION:
7268 newss = gfc_get_ss ();
7269 newss->type = GFC_SS_SECTION;
7270 newss->expr = expr;
7271 newss->next = ss;
7272 newss->data.info.dimen = 0;
7273 newss->data.info.ref = ref;
7275 /* We add SS chains for all the subscripts in the section. */
7276 for (n = 0; n < ar->dimen; n++)
7278 gfc_ss *indexss;
7280 switch (ar->dimen_type[n])
7282 case DIMEN_ELEMENT:
7283 /* Add SS for elemental (scalar) subscripts. */
7284 gcc_assert (ar->start[n]);
7285 indexss = gfc_get_ss ();
7286 indexss->type = GFC_SS_SCALAR;
7287 indexss->expr = ar->start[n];
7288 indexss->next = gfc_ss_terminator;
7289 indexss->loop_chain = gfc_ss_terminator;
7290 newss->data.info.subscript[n] = indexss;
7291 break;
7293 case DIMEN_RANGE:
7294 /* We don't add anything for sections, just remember this
7295 dimension for later. */
7296 newss->data.info.dim[newss->data.info.dimen] = n;
7297 newss->data.info.dimen++;
7298 break;
7300 case DIMEN_VECTOR:
7301 /* Create a GFC_SS_VECTOR index in which we can store
7302 the vector's descriptor. */
7303 indexss = gfc_get_ss ();
7304 indexss->type = GFC_SS_VECTOR;
7305 indexss->expr = ar->start[n];
7306 indexss->next = gfc_ss_terminator;
7307 indexss->loop_chain = gfc_ss_terminator;
7308 newss->data.info.subscript[n] = indexss;
7309 newss->data.info.dim[newss->data.info.dimen] = n;
7310 newss->data.info.dimen++;
7311 break;
7313 default:
7314 /* We should know what sort of section it is by now. */
7315 gcc_unreachable ();
7318 /* We should have at least one non-elemental dimension. */
7319 gcc_assert (newss->data.info.dimen > 0);
7320 ss = newss;
7321 break;
7323 default:
7324 /* We should know what sort of section it is by now. */
7325 gcc_unreachable ();
7329 return ss;
7333 /* Walk an expression operator. If only one operand of a binary expression is
7334 scalar, we must also add the scalar term to the SS chain. */
7336 static gfc_ss *
7337 gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
7339 gfc_ss *head;
7340 gfc_ss *head2;
7341 gfc_ss *newss;
7343 head = gfc_walk_subexpr (ss, expr->value.op.op1);
7344 if (expr->value.op.op2 == NULL)
7345 head2 = head;
7346 else
7347 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
7349 /* All operands are scalar. Pass back and let the caller deal with it. */
7350 if (head2 == ss)
7351 return head2;
7353 /* All operands require scalarization. */
7354 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
7355 return head2;
7357 /* One of the operands needs scalarization, the other is scalar.
7358 Create a gfc_ss for the scalar expression. */
7359 newss = gfc_get_ss ();
7360 newss->type = GFC_SS_SCALAR;
7361 if (head == ss)
7363 /* First operand is scalar. We build the chain in reverse order, so
7364 add the scalar SS after the second operand. */
7365 head = head2;
7366 while (head && head->next != ss)
7367 head = head->next;
7368 /* Check we haven't somehow broken the chain. */
7369 gcc_assert (head);
7370 newss->next = ss;
7371 head->next = newss;
7372 newss->expr = expr->value.op.op1;
7374 else /* head2 == head */
7376 gcc_assert (head2 == head);
7377 /* Second operand is scalar. */
7378 newss->next = head2;
7379 head2 = newss;
7380 newss->expr = expr->value.op.op2;
7383 return head2;
7387 /* Reverse a SS chain. */
7389 gfc_ss *
7390 gfc_reverse_ss (gfc_ss * ss)
7392 gfc_ss *next;
7393 gfc_ss *head;
7395 gcc_assert (ss != NULL);
7397 head = gfc_ss_terminator;
7398 while (ss != gfc_ss_terminator)
7400 next = ss->next;
7401 /* Check we didn't somehow break the chain. */
7402 gcc_assert (next != NULL);
7403 ss->next = head;
7404 head = ss;
7405 ss = next;
7408 return (head);
7412 /* Walk the arguments of an elemental function. */
7414 gfc_ss *
7415 gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
7416 gfc_ss_type type)
7418 int scalar;
7419 gfc_ss *head;
7420 gfc_ss *tail;
7421 gfc_ss *newss;
7423 head = gfc_ss_terminator;
7424 tail = NULL;
7425 scalar = 1;
7426 for (; arg; arg = arg->next)
7428 if (!arg->expr)
7429 continue;
7431 newss = gfc_walk_subexpr (head, arg->expr);
7432 if (newss == head)
7434 /* Scalar argument. */
7435 newss = gfc_get_ss ();
7436 newss->type = type;
7437 newss->expr = arg->expr;
7438 newss->next = head;
7440 else
7441 scalar = 0;
7443 head = newss;
7444 if (!tail)
7446 tail = head;
7447 while (tail->next != gfc_ss_terminator)
7448 tail = tail->next;
7452 if (scalar)
7454 /* If all the arguments are scalar we don't need the argument SS. */
7455 gfc_free_ss_chain (head);
7456 /* Pass it back. */
7457 return ss;
7460 /* Add it onto the existing chain. */
7461 tail->next = ss;
7462 return head;
7466 /* Walk a function call. Scalar functions are passed back, and taken out of
7467 scalarization loops. For elemental functions we walk their arguments.
7468 The result of functions returning arrays is stored in a temporary outside
7469 the loop, so that the function is only called once. Hence we do not need
7470 to walk their arguments. */
7472 static gfc_ss *
7473 gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
7475 gfc_ss *newss;
7476 gfc_intrinsic_sym *isym;
7477 gfc_symbol *sym;
7478 gfc_component *comp = NULL;
7479 int n;
7481 isym = expr->value.function.isym;
7483 /* Handle intrinsic functions separately. */
7484 if (isym)
7485 return gfc_walk_intrinsic_function (ss, expr, isym);
7487 sym = expr->value.function.esym;
7488 if (!sym)
7489 sym = expr->symtree->n.sym;
7491 /* A function that returns arrays. */
7492 gfc_is_proc_ptr_comp (expr, &comp);
7493 if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
7494 || (comp && comp->attr.dimension))
7496 newss = gfc_get_ss ();
7497 newss->type = GFC_SS_FUNCTION;
7498 newss->expr = expr;
7499 newss->next = ss;
7500 newss->data.info.dimen = expr->rank;
7501 for (n = 0; n < newss->data.info.dimen; n++)
7502 newss->data.info.dim[n] = n;
7503 return newss;
7506 /* Walk the parameters of an elemental function. For now we always pass
7507 by reference. */
7508 if (sym->attr.elemental)
7509 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
7510 GFC_SS_REFERENCE);
7512 /* Scalar functions are OK as these are evaluated outside the scalarization
7513 loop. Pass back and let the caller deal with it. */
7514 return ss;
7518 /* An array temporary is constructed for array constructors. */
7520 static gfc_ss *
7521 gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
7523 gfc_ss *newss;
7524 int n;
7526 newss = gfc_get_ss ();
7527 newss->type = GFC_SS_CONSTRUCTOR;
7528 newss->expr = expr;
7529 newss->next = ss;
7530 newss->data.info.dimen = expr->rank;
7531 for (n = 0; n < expr->rank; n++)
7532 newss->data.info.dim[n] = n;
7534 return newss;
7538 /* Walk an expression. Add walked expressions to the head of the SS chain.
7539 A wholly scalar expression will not be added. */
7541 gfc_ss *
7542 gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
7544 gfc_ss *head;
7546 switch (expr->expr_type)
7548 case EXPR_VARIABLE:
7549 head = gfc_walk_variable_expr (ss, expr);
7550 return head;
7552 case EXPR_OP:
7553 head = gfc_walk_op_expr (ss, expr);
7554 return head;
7556 case EXPR_FUNCTION:
7557 head = gfc_walk_function_expr (ss, expr);
7558 return head;
7560 case EXPR_CONSTANT:
7561 case EXPR_NULL:
7562 case EXPR_STRUCTURE:
7563 /* Pass back and let the caller deal with it. */
7564 break;
7566 case EXPR_ARRAY:
7567 head = gfc_walk_array_constructor (ss, expr);
7568 return head;
7570 case EXPR_SUBSTRING:
7571 /* Pass back and let the caller deal with it. */
7572 break;
7574 default:
7575 internal_error ("bad expression type during walk (%d)",
7576 expr->expr_type);
7578 return ss;
7582 /* Entry point for expression walking.
7583 A return value equal to the passed chain means this is
7584 a scalar expression. It is up to the caller to take whatever action is
7585 necessary to translate these. */
7587 gfc_ss *
7588 gfc_walk_expr (gfc_expr * expr)
7590 gfc_ss *res;
7592 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
7593 return gfc_reverse_ss (res);