]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-array.c
tree-ssa-alias.h (dump_points_to_solution): Declare.
[thirdparty/gcc.git] / gcc / fortran / trans-array.c
CommitLineData
6de9cd9a 1/* Array translation routines
d3d3011f 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
114e4d10 3 Free Software Foundation, Inc.
6de9cd9a
DN
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6
9fc4d79b 7This file is part of GCC.
6de9cd9a 8
9fc4d79b
TS
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
d234d788 11Software Foundation; either version 3, or (at your option) any later
9fc4d79b 12version.
6de9cd9a 13
9fc4d79b
TS
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
6de9cd9a
DN
18
19You should have received a copy of the GNU General Public License
d234d788
NC
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
6de9cd9a
DN
22
23/* trans-array.c-- Various array related code, including scalarization,
24 allocation, initialization and other support routines. */
25
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.
32
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.
37
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
df2fba9e 42 or vector subscripts as procedure parameters.
6de9cd9a
DN
43
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.
48
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.
55
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.
60
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
1f2959f0 63 values are automatically substituted. Note that gfc_advance_se_ss_chain
6de9cd9a
DN
64 must be used, rather than changing the se->ss directly.
65
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.
71
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.
75
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. */
78
79#include "config.h"
80#include "system.h"
81#include "coretypes.h"
82#include "tree.h"
726a989a 83#include "gimple.h"
6de9cd9a
DN
84#include "ggc.h"
85#include "toplev.h"
86#include "real.h"
87#include "flags.h"
6de9cd9a
DN
88#include "gfortran.h"
89#include "trans.h"
90#include "trans-stmt.h"
91#include "trans-types.h"
92#include "trans-array.h"
93#include "trans-const.h"
94#include "dependency.h"
95
96static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
ec25720b 97static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor *);
6de9cd9a 98
13413760 99/* The contents of this structure aren't actually used, just the address. */
6de9cd9a
DN
100static gfc_ss gfc_ss_terminator_var;
101gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
102
6de9cd9a
DN
103
104static tree
105gfc_array_dataptr_type (tree desc)
106{
107 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
108}
109
110
111/* Build expressions to access the members of an array descriptor.
112 It's surprisingly easy to mess up here, so never access
113 an array descriptor by "brute force", always use these
114 functions. This also avoids problems if we change the format
115 of an array descriptor.
116
117 To understand these magic numbers, look at the comments
118 before gfc_build_array_type() in trans-types.c.
119
120 The code within these defines should be the only code which knows the format
121 of an array descriptor.
122
123 Any code just needing to read obtain the bounds of an array should use
124 gfc_conv_array_* rather than the following functions as these will return
125 know constant values, and work with arrays which do not have descriptors.
126
127 Don't forget to #undef these! */
128
129#define DATA_FIELD 0
130#define OFFSET_FIELD 1
131#define DTYPE_FIELD 2
132#define DIMENSION_FIELD 3
133
134#define STRIDE_SUBFIELD 0
135#define LBOUND_SUBFIELD 1
136#define UBOUND_SUBFIELD 2
137
4c73896d
RH
138/* This provides READ-ONLY access to the data field. The field itself
139 doesn't have the proper type. */
140
6de9cd9a 141tree
4c73896d 142gfc_conv_descriptor_data_get (tree desc)
6de9cd9a 143{
4c73896d 144 tree field, type, t;
6de9cd9a
DN
145
146 type = TREE_TYPE (desc);
6e45f57b 147 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
148
149 field = TYPE_FIELDS (type);
6e45f57b 150 gcc_assert (DATA_FIELD == 0);
6de9cd9a 151
44855d8c 152 t = fold_build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
4c73896d
RH
153 t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);
154
155 return t;
156}
157
07beea0d
AH
158/* This provides WRITE access to the data field.
159
160 TUPLES_P is true if we are generating tuples.
161
162 This function gets called through the following macros:
163 gfc_conv_descriptor_data_set
726a989a 164 gfc_conv_descriptor_data_set. */
4c73896d
RH
165
166void
726a989a 167gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
4c73896d
RH
168{
169 tree field, type, t;
170
171 type = TREE_TYPE (desc);
172 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
173
174 field = TYPE_FIELDS (type);
175 gcc_assert (DATA_FIELD == 0);
176
44855d8c 177 t = fold_build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
726a989a 178 gfc_add_modify (block, t, fold_convert (TREE_TYPE (field), value));
4c73896d
RH
179}
180
181
182/* This provides address access to the data field. This should only be
183 used by array allocation, passing this on to the runtime. */
184
185tree
186gfc_conv_descriptor_data_addr (tree desc)
187{
188 tree field, type, t;
189
190 type = TREE_TYPE (desc);
191 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
192
193 field = TYPE_FIELDS (type);
194 gcc_assert (DATA_FIELD == 0);
195
44855d8c 196 t = fold_build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
628c189e 197 return gfc_build_addr_expr (NULL_TREE, t);
6de9cd9a
DN
198}
199
200tree
201gfc_conv_descriptor_offset (tree desc)
202{
203 tree type;
204 tree field;
205
206 type = TREE_TYPE (desc);
6e45f57b 207 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
208
209 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
6e45f57b 210 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 211
44855d8c
TS
212 return fold_build3 (COMPONENT_REF, TREE_TYPE (field),
213 desc, field, NULL_TREE);
6de9cd9a
DN
214}
215
216tree
217gfc_conv_descriptor_dtype (tree desc)
218{
219 tree field;
220 tree type;
221
222 type = TREE_TYPE (desc);
6e45f57b 223 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
224
225 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
6e45f57b 226 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 227
44855d8c
TS
228 return fold_build3 (COMPONENT_REF, TREE_TYPE (field),
229 desc, field, NULL_TREE);
6de9cd9a
DN
230}
231
232static tree
233gfc_conv_descriptor_dimension (tree desc, tree dim)
234{
235 tree field;
236 tree type;
237 tree tmp;
238
239 type = TREE_TYPE (desc);
6e45f57b 240 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
241
242 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
6e45f57b 243 gcc_assert (field != NULL_TREE
6de9cd9a
DN
244 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
245 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
246
44855d8c
TS
247 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
248 desc, field, NULL_TREE);
1d6b7f39 249 tmp = gfc_build_array_ref (tmp, dim, NULL);
6de9cd9a
DN
250 return tmp;
251}
252
253tree
254gfc_conv_descriptor_stride (tree desc, tree dim)
255{
256 tree tmp;
257 tree field;
258
259 tmp = gfc_conv_descriptor_dimension (desc, dim);
260 field = TYPE_FIELDS (TREE_TYPE (tmp));
261 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
6e45f57b 262 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 263
44855d8c
TS
264 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
265 tmp, field, NULL_TREE);
6de9cd9a
DN
266 return tmp;
267}
268
269tree
270gfc_conv_descriptor_lbound (tree desc, tree dim)
271{
272 tree tmp;
273 tree field;
274
275 tmp = gfc_conv_descriptor_dimension (desc, dim);
276 field = TYPE_FIELDS (TREE_TYPE (tmp));
277 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
6e45f57b 278 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 279
44855d8c
TS
280 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
281 tmp, field, NULL_TREE);
6de9cd9a
DN
282 return tmp;
283}
284
285tree
286gfc_conv_descriptor_ubound (tree desc, tree dim)
287{
288 tree tmp;
289 tree field;
290
291 tmp = gfc_conv_descriptor_dimension (desc, dim);
292 field = TYPE_FIELDS (TREE_TYPE (tmp));
293 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
6e45f57b 294 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 295
44855d8c
TS
296 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
297 tmp, field, NULL_TREE);
6de9cd9a
DN
298 return tmp;
299}
300
301
49de9e73 302/* Build a null array descriptor constructor. */
6de9cd9a 303
331c72f3
PB
304tree
305gfc_build_null_descriptor (tree type)
6de9cd9a 306{
6de9cd9a 307 tree field;
331c72f3 308 tree tmp;
6de9cd9a 309
6e45f57b
PB
310 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
311 gcc_assert (DATA_FIELD == 0);
6de9cd9a
DN
312 field = TYPE_FIELDS (type);
313
331c72f3 314 /* Set a NULL data pointer. */
4038c495 315 tmp = build_constructor_single (type, field, null_pointer_node);
6de9cd9a 316 TREE_CONSTANT (tmp) = 1;
331c72f3
PB
317 /* All other fields are ignored. */
318
319 return tmp;
6de9cd9a
DN
320}
321
322
323/* Cleanup those #defines. */
324
325#undef DATA_FIELD
326#undef OFFSET_FIELD
327#undef DTYPE_FIELD
328#undef DIMENSION_FIELD
329#undef STRIDE_SUBFIELD
330#undef LBOUND_SUBFIELD
331#undef UBOUND_SUBFIELD
332
333
334/* Mark a SS chain as used. Flags specifies in which loops the SS is used.
335 flags & 1 = Main loop body.
336 flags & 2 = temp copy loop. */
337
338void
339gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
340{
341 for (; ss != gfc_ss_terminator; ss = ss->next)
342 ss->useflags = flags;
343}
344
345static void gfc_free_ss (gfc_ss *);
346
347
348/* Free a gfc_ss chain. */
349
350static void
351gfc_free_ss_chain (gfc_ss * ss)
352{
353 gfc_ss *next;
354
355 while (ss != gfc_ss_terminator)
356 {
6e45f57b 357 gcc_assert (ss != NULL);
6de9cd9a
DN
358 next = ss->next;
359 gfc_free_ss (ss);
360 ss = next;
361 }
362}
363
364
365/* Free a SS. */
366
367static void
368gfc_free_ss (gfc_ss * ss)
369{
370 int n;
371
372 switch (ss->type)
373 {
374 case GFC_SS_SECTION:
6de9cd9a
DN
375 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
376 {
377 if (ss->data.info.subscript[n])
378 gfc_free_ss_chain (ss->data.info.subscript[n]);
379 }
380 break;
381
382 default:
383 break;
384 }
385
386 gfc_free (ss);
387}
388
389
390/* Free all the SS associated with a loop. */
391
392void
393gfc_cleanup_loop (gfc_loopinfo * loop)
394{
395 gfc_ss *ss;
396 gfc_ss *next;
397
398 ss = loop->ss;
399 while (ss != gfc_ss_terminator)
400 {
6e45f57b 401 gcc_assert (ss != NULL);
6de9cd9a
DN
402 next = ss->loop_chain;
403 gfc_free_ss (ss);
404 ss = next;
405 }
406}
407
408
409/* Associate a SS chain with a loop. */
410
411void
412gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
413{
414 gfc_ss *ss;
415
416 if (head == gfc_ss_terminator)
417 return;
418
419 ss = head;
420 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
421 {
422 if (ss->next == gfc_ss_terminator)
423 ss->loop_chain = loop->ss;
424 else
425 ss->loop_chain = ss->next;
426 }
6e45f57b 427 gcc_assert (ss == gfc_ss_terminator);
6de9cd9a
DN
428 loop->ss = head;
429}
430
431
331c72f3
PB
432/* Generate an initializer for a static pointer or allocatable array. */
433
434void
435gfc_trans_static_array_pointer (gfc_symbol * sym)
436{
437 tree type;
438
6e45f57b 439 gcc_assert (TREE_STATIC (sym->backend_decl));
331c72f3
PB
440 /* Just zero the data member. */
441 type = TREE_TYPE (sym->backend_decl);
df7df328 442 DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);
331c72f3
PB
443}
444
445
62ab4a54
RS
446/* If the bounds of SE's loop have not yet been set, see if they can be
447 determined from array spec AS, which is the array spec of a called
448 function. MAPPING maps the callee's dummy arguments to the values
449 that the caller is passing. Add any initialization and finalization
450 code to SE. */
451
452void
453gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
454 gfc_se * se, gfc_array_spec * as)
455{
456 int n, dim;
457 gfc_se tmpse;
458 tree lower;
459 tree upper;
460 tree tmp;
461
462 if (as && as->type == AS_EXPLICIT)
463 for (dim = 0; dim < se->loop->dimen; dim++)
464 {
465 n = se->loop->order[dim];
466 if (se->loop->to[n] == NULL_TREE)
467 {
468 /* Evaluate the lower bound. */
469 gfc_init_se (&tmpse, NULL);
470 gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);
471 gfc_add_block_to_block (&se->pre, &tmpse.pre);
472 gfc_add_block_to_block (&se->post, &tmpse.post);
795dc587 473 lower = fold_convert (gfc_array_index_type, tmpse.expr);
62ab4a54
RS
474
475 /* ...and the upper bound. */
476 gfc_init_se (&tmpse, NULL);
477 gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
478 gfc_add_block_to_block (&se->pre, &tmpse.pre);
479 gfc_add_block_to_block (&se->post, &tmpse.post);
795dc587 480 upper = fold_convert (gfc_array_index_type, tmpse.expr);
62ab4a54
RS
481
482 /* Set the upper bound of the loop to UPPER - LOWER. */
483 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);
484 tmp = gfc_evaluate_now (tmp, &se->pre);
485 se->loop->to[n] = tmp;
486 }
487 }
488}
489
490
6de9cd9a 491/* Generate code to allocate an array temporary, or create a variable to
5b0b7251
EE
492 hold the data. If size is NULL, zero the descriptor so that the
493 callee will allocate the array. If DEALLOC is true, also generate code to
494 free the array afterwards.
ec25720b 495
12f681a0
DK
496 If INITIAL is not NULL, it is packed using internal_pack and the result used
497 as data instead of allocating a fresh, unitialized area of memory.
498
62ab4a54 499 Initialization code is added to PRE and finalization code to POST.
ec25720b
RS
500 DYNAMIC is true if the caller may want to extend the array later
501 using realloc. This prevents us from putting the array on the stack. */
6de9cd9a
DN
502
503static void
62ab4a54 504gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
12f681a0
DK
505 gfc_ss_info * info, tree size, tree nelem,
506 tree initial, bool dynamic, bool dealloc)
6de9cd9a
DN
507{
508 tree tmp;
6de9cd9a 509 tree desc;
6de9cd9a
DN
510 bool onstack;
511
512 desc = info->descriptor;
4c73896d 513 info->offset = gfc_index_zero_node;
ec25720b 514 if (size == NULL_TREE || integer_zerop (size))
6de9cd9a 515 {
fc90a8f2 516 /* A callee allocated array. */
62ab4a54 517 gfc_conv_descriptor_data_set (pre, desc, null_pointer_node);
fc90a8f2 518 onstack = FALSE;
6de9cd9a
DN
519 }
520 else
521 {
fc90a8f2 522 /* Allocate the temporary. */
12f681a0
DK
523 onstack = !dynamic && initial == NULL_TREE
524 && gfc_can_put_var_on_stack (size);
fc90a8f2
PB
525
526 if (onstack)
527 {
528 /* Make a temporary variable to hold the data. */
10c7a96f 529 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (nelem), nelem,
37da9343 530 gfc_index_one_node);
fc90a8f2
PB
531 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
532 tmp);
533 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
534 tmp);
535 tmp = gfc_create_var (tmp, "A");
628c189e 536 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
62ab4a54 537 gfc_conv_descriptor_data_set (pre, desc, tmp);
fc90a8f2 538 }
6de9cd9a 539 else
fc90a8f2 540 {
12f681a0
DK
541 /* Allocate memory to hold the data or call internal_pack. */
542 if (initial == NULL_TREE)
543 {
544 tmp = gfc_call_malloc (pre, NULL, size);
545 tmp = gfc_evaluate_now (tmp, pre);
546 }
547 else
548 {
549 tree packed;
550 tree source_data;
551 tree was_packed;
552 stmtblock_t do_copying;
553
554 tmp = TREE_TYPE (initial); /* Pointer to descriptor. */
555 gcc_assert (TREE_CODE (tmp) == POINTER_TYPE);
556 tmp = TREE_TYPE (tmp); /* The descriptor itself. */
557 tmp = gfc_get_element_type (tmp);
558 gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
559 packed = gfc_create_var (build_pointer_type (tmp), "data");
560
561 tmp = build_call_expr (gfor_fndecl_in_pack, 1, initial);
562 tmp = fold_convert (TREE_TYPE (packed), tmp);
563 gfc_add_modify (pre, packed, tmp);
564
565 tmp = build_fold_indirect_ref (initial);
566 source_data = gfc_conv_descriptor_data_get (tmp);
567
568 /* internal_pack may return source->data without any allocation
569 or copying if it is already packed. If that's the case, we
570 need to allocate and copy manually. */
571
572 gfc_start_block (&do_copying);
573 tmp = gfc_call_malloc (&do_copying, NULL, size);
574 tmp = fold_convert (TREE_TYPE (packed), tmp);
575 gfc_add_modify (&do_copying, packed, tmp);
576 tmp = gfc_build_memcpy_call (packed, source_data, size);
577 gfc_add_expr_to_block (&do_copying, tmp);
578
579 was_packed = fold_build2 (EQ_EXPR, boolean_type_node,
580 packed, source_data);
581 tmp = gfc_finish_block (&do_copying);
582 tmp = build3_v (COND_EXPR, was_packed, tmp, build_empty_stmt ());
583 gfc_add_expr_to_block (pre, tmp);
584
585 tmp = fold_convert (pvoid_type_node, packed);
586 }
587
62ab4a54 588 gfc_conv_descriptor_data_set (pre, desc, tmp);
fc90a8f2 589 }
6de9cd9a 590 }
4c73896d 591 info->data = gfc_conv_descriptor_data_get (desc);
6de9cd9a
DN
592
593 /* The offset is zero because we create temporaries with a zero
594 lower bound. */
595 tmp = gfc_conv_descriptor_offset (desc);
726a989a 596 gfc_add_modify (pre, tmp, gfc_index_zero_node);
6de9cd9a 597
5b0b7251 598 if (dealloc && !onstack)
6de9cd9a
DN
599 {
600 /* Free the temporary. */
4c73896d 601 tmp = gfc_conv_descriptor_data_get (desc);
1529b8d9 602 tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp));
62ab4a54 603 gfc_add_expr_to_block (post, tmp);
6de9cd9a
DN
604 }
605}
606
607
8e119f1b 608/* Generate code to create and initialize the descriptor for a temporary
e7dc5b4f 609 array. This is used for both temporaries needed by the scalarizer, and
8e119f1b
EE
610 functions returning arrays. Adjusts the loop variables to be
611 zero-based, and calculates the loop bounds for callee allocated arrays.
612 Allocate the array unless it's callee allocated (we have a callee
613 allocated array if 'callee_alloc' is true, or if loop->to[n] is
614 NULL_TREE for any n). Also fills in the descriptor, data and offset
615 fields of info if known. Returns the size of the array, or NULL for a
616 callee allocated array.
ec25720b 617
12f681a0
DK
618 PRE, POST, INITIAL, DYNAMIC and DEALLOC are as for
619 gfc_trans_allocate_array_storage.
5b0b7251 620 */
6de9cd9a
DN
621
622tree
8e119f1b
EE
623gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
624 gfc_loopinfo * loop, gfc_ss_info * info,
12f681a0
DK
625 tree eltype, tree initial, bool dynamic,
626 bool dealloc, bool callee_alloc, locus * where)
6de9cd9a
DN
627{
628 tree type;
629 tree desc;
630 tree tmp;
631 tree size;
632 tree nelem;
da4340a1
TK
633 tree cond;
634 tree or_expr;
6de9cd9a
DN
635 int n;
636 int dim;
637
6e45f57b 638 gcc_assert (info->dimen > 0);
bdfd2ff0
TK
639
640 if (gfc_option.warn_array_temp && where)
641 gfc_warning ("Creating array temporary at %L", where);
642
6de9cd9a
DN
643 /* Set the lower bound to zero. */
644 for (dim = 0; dim < info->dimen; dim++)
645 {
646 n = loop->order[dim];
22089905
PT
647 /* Callee allocated arrays may not have a known bound yet. */
648 if (loop->to[n])
649 loop->to[n] = gfc_evaluate_now (fold_build2 (MINUS_EXPR,
650 gfc_array_index_type,
651 loop->to[n], loop->from[n]), pre);
652 loop->from[n] = gfc_index_zero_node;
6de9cd9a 653
7ab92584
SB
654 info->delta[dim] = gfc_index_zero_node;
655 info->start[dim] = gfc_index_zero_node;
8424e0d8 656 info->end[dim] = gfc_index_zero_node;
7ab92584 657 info->stride[dim] = gfc_index_one_node;
6de9cd9a
DN
658 info->dim[dim] = dim;
659 }
660
13413760 661 /* Initialize the descriptor. */
6de9cd9a 662 type =
fad0afd7
JJ
663 gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1,
664 GFC_ARRAY_UNKNOWN);
6de9cd9a
DN
665 desc = gfc_create_var (type, "atmp");
666 GFC_DECL_PACKED_ARRAY (desc) = 1;
667
668 info->descriptor = desc;
7ab92584 669 size = gfc_index_one_node;
6de9cd9a
DN
670
671 /* Fill in the array dtype. */
672 tmp = gfc_conv_descriptor_dtype (desc);
726a989a 673 gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
6de9cd9a 674
7ab92584
SB
675 /*
676 Fill in the bounds and stride. This is a packed array, so:
677
6de9cd9a
DN
678 size = 1;
679 for (n = 0; n < rank; n++)
7ab92584
SB
680 {
681 stride[n] = size
682 delta = ubound[n] + 1 - lbound[n];
12f681a0 683 size = size * delta;
7ab92584
SB
684 }
685 size = size * sizeof(element);
686 */
687
da4340a1
TK
688 or_expr = NULL_TREE;
689
45bc572c
MM
690 /* If there is at least one null loop->to[n], it is a callee allocated
691 array. */
6de9cd9a 692 for (n = 0; n < info->dimen; n++)
45bc572c
MM
693 if (loop->to[n] == NULL_TREE)
694 {
695 size = NULL_TREE;
696 break;
697 }
698
699 for (n = 0; n < info->dimen; n++)
700 {
701 if (size == NULL_TREE)
12f681a0 702 {
fc90a8f2
PB
703 /* For a callee allocated array express the loop bounds in terms
704 of the descriptor fields. */
12f681a0 705 tmp =
44855d8c
TS
706 fold_build2 (MINUS_EXPR, gfc_array_index_type,
707 gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
708 gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
12f681a0
DK
709 loop->to[n] = tmp;
710 continue;
711 }
712
6de9cd9a
DN
713 /* Store the stride and bound components in the descriptor. */
714 tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
726a989a 715 gfc_add_modify (pre, tmp, size);
6de9cd9a
DN
716
717 tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
726a989a 718 gfc_add_modify (pre, tmp, gfc_index_zero_node);
6de9cd9a
DN
719
720 tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
726a989a 721 gfc_add_modify (pre, tmp, loop->to[n]);
6de9cd9a 722
10c7a96f
SB
723 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
724 loop->to[n], gfc_index_one_node);
6de9cd9a 725
999ffb1a
FXC
726 /* Check whether the size for this dimension is negative. */
727 cond = fold_build2 (LE_EXPR, boolean_type_node, tmp,
da4340a1 728 gfc_index_zero_node);
999ffb1a 729 cond = gfc_evaluate_now (cond, pre);
da4340a1 730
999ffb1a
FXC
731 if (n == 0)
732 or_expr = cond;
733 else
734 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
da4340a1 735
10c7a96f 736 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
62ab4a54 737 size = gfc_evaluate_now (size, pre);
6de9cd9a
DN
738 }
739
6de9cd9a 740 /* Get the size of the array. */
da4340a1 741
8e119f1b 742 if (size && !callee_alloc)
da4340a1 743 {
999ffb1a
FXC
744 /* If or_expr is true, then the extent in at least one
745 dimension is zero and the size is set to zero. */
746 size = fold_build3 (COND_EXPR, gfc_array_index_type,
747 or_expr, gfc_index_zero_node, size);
da4340a1 748
fcac9229 749 nelem = size;
da4340a1 750 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
7c57b2f1
FXC
751 fold_convert (gfc_array_index_type,
752 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
da4340a1 753 }
8e119f1b 754 else
da4340a1
TK
755 {
756 nelem = size;
757 size = NULL_TREE;
758 }
6de9cd9a 759
12f681a0
DK
760 gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
761 dynamic, dealloc);
6de9cd9a
DN
762
763 if (info->dimen > loop->temp_dim)
764 loop->temp_dim = info->dimen;
765
766 return size;
767}
768
769
8a6c4339 770/* Generate code to transpose array EXPR by creating a new descriptor
1524f80b
RS
771 in which the dimension specifications have been reversed. */
772
773void
774gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
775{
776 tree dest, src, dest_index, src_index;
777 gfc_loopinfo *loop;
778 gfc_ss_info *dest_info, *src_info;
779 gfc_ss *dest_ss, *src_ss;
780 gfc_se src_se;
781 int n;
782
783 loop = se->loop;
784
785 src_ss = gfc_walk_expr (expr);
786 dest_ss = se->ss;
787
788 src_info = &src_ss->data.info;
789 dest_info = &dest_ss->data.info;
c69a7fb7
L
790 gcc_assert (dest_info->dimen == 2);
791 gcc_assert (src_info->dimen == 2);
1524f80b
RS
792
793 /* Get a descriptor for EXPR. */
794 gfc_init_se (&src_se, NULL);
795 gfc_conv_expr_descriptor (&src_se, expr, src_ss);
796 gfc_add_block_to_block (&se->pre, &src_se.pre);
797 gfc_add_block_to_block (&se->post, &src_se.post);
798 src = src_se.expr;
799
800 /* Allocate a new descriptor for the return value. */
801 dest = gfc_create_var (TREE_TYPE (src), "atmp");
802 dest_info->descriptor = dest;
803 se->expr = dest;
804
805 /* Copy across the dtype field. */
726a989a 806 gfc_add_modify (&se->pre,
1524f80b
RS
807 gfc_conv_descriptor_dtype (dest),
808 gfc_conv_descriptor_dtype (src));
809
810 /* Copy the dimension information, renumbering dimension 1 to 0 and
811 0 to 1. */
1524f80b
RS
812 for (n = 0; n < 2; n++)
813 {
37da9343
RS
814 dest_info->delta[n] = gfc_index_zero_node;
815 dest_info->start[n] = gfc_index_zero_node;
8424e0d8 816 dest_info->end[n] = gfc_index_zero_node;
37da9343 817 dest_info->stride[n] = gfc_index_one_node;
1524f80b
RS
818 dest_info->dim[n] = n;
819
820 dest_index = gfc_rank_cst[n];
821 src_index = gfc_rank_cst[1 - n];
822
726a989a 823 gfc_add_modify (&se->pre,
1524f80b
RS
824 gfc_conv_descriptor_stride (dest, dest_index),
825 gfc_conv_descriptor_stride (src, src_index));
826
726a989a 827 gfc_add_modify (&se->pre,
1524f80b
RS
828 gfc_conv_descriptor_lbound (dest, dest_index),
829 gfc_conv_descriptor_lbound (src, src_index));
830
726a989a 831 gfc_add_modify (&se->pre,
1524f80b
RS
832 gfc_conv_descriptor_ubound (dest, dest_index),
833 gfc_conv_descriptor_ubound (src, src_index));
834
835 if (!loop->to[n])
836 {
837 gcc_assert (integer_zerop (loop->from[n]));
44855d8c
TS
838 loop->to[n] =
839 fold_build2 (MINUS_EXPR, gfc_array_index_type,
840 gfc_conv_descriptor_ubound (dest, dest_index),
841 gfc_conv_descriptor_lbound (dest, dest_index));
1524f80b
RS
842 }
843 }
844
845 /* Copy the data pointer. */
846 dest_info->data = gfc_conv_descriptor_data_get (src);
847 gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);
848
1229ece0
PT
849 /* Copy the offset. This is not changed by transposition; the top-left
850 element is still at the same offset as before, except where the loop
851 starts at zero. */
852 if (!integer_zerop (loop->from[0]))
853 dest_info->offset = gfc_conv_descriptor_offset (src);
854 else
855 dest_info->offset = gfc_index_zero_node;
856
726a989a 857 gfc_add_modify (&se->pre,
1524f80b
RS
858 gfc_conv_descriptor_offset (dest),
859 dest_info->offset);
1229ece0 860
1524f80b
RS
861 if (dest_info->dimen > loop->temp_dim)
862 loop->temp_dim = dest_info->dimen;
863}
864
865
ec25720b
RS
866/* Return the number of iterations in a loop that starts at START,
867 ends at END, and has step STEP. */
868
869static tree
870gfc_get_iteration_count (tree start, tree end, tree step)
871{
872 tree tmp;
873 tree type;
874
875 type = TREE_TYPE (step);
876 tmp = fold_build2 (MINUS_EXPR, type, end, start);
877 tmp = fold_build2 (FLOOR_DIV_EXPR, type, tmp, step);
878 tmp = fold_build2 (PLUS_EXPR, type, tmp, build_int_cst (type, 1));
879 tmp = fold_build2 (MAX_EXPR, type, tmp, build_int_cst (type, 0));
880 return fold_convert (gfc_array_index_type, tmp);
881}
882
883
884/* Extend the data in array DESC by EXTRA elements. */
885
886static void
887gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
888{
5039610b 889 tree arg0, arg1;
ec25720b
RS
890 tree tmp;
891 tree size;
892 tree ubound;
893
894 if (integer_zerop (extra))
895 return;
896
897 ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
898
899 /* Add EXTRA to the upper bound. */
44855d8c 900 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
726a989a 901 gfc_add_modify (pblock, ubound, tmp);
ec25720b
RS
902
903 /* Get the value of the current data pointer. */
5039610b 904 arg0 = gfc_conv_descriptor_data_get (desc);
ec25720b
RS
905
906 /* Calculate the new array size. */
907 size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
44855d8c
TS
908 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
909 ubound, gfc_index_one_node);
910 arg1 = fold_build2 (MULT_EXPR, size_type_node,
911 fold_convert (size_type_node, tmp),
912 fold_convert (size_type_node, size));
ec25720b 913
4376b7cf
FXC
914 /* Call the realloc() function. */
915 tmp = gfc_call_realloc (pblock, arg0, arg1);
ec25720b
RS
916 gfc_conv_descriptor_data_set (pblock, desc, tmp);
917}
918
919
920/* Return true if the bounds of iterator I can only be determined
921 at run time. */
922
923static inline bool
924gfc_iterator_has_dynamic_bounds (gfc_iterator * i)
925{
926 return (i->start->expr_type != EXPR_CONSTANT
927 || i->end->expr_type != EXPR_CONSTANT
928 || i->step->expr_type != EXPR_CONSTANT);
929}
930
931
932/* Split the size of constructor element EXPR into the sum of two terms,
933 one of which can be determined at compile time and one of which must
934 be calculated at run time. Set *SIZE to the former and return true
935 if the latter might be nonzero. */
936
937static bool
938gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
939{
940 if (expr->expr_type == EXPR_ARRAY)
941 return gfc_get_array_constructor_size (size, expr->value.constructor);
942 else if (expr->rank > 0)
943 {
944 /* Calculate everything at run time. */
945 mpz_set_ui (*size, 0);
946 return true;
947 }
948 else
949 {
950 /* A single element. */
951 mpz_set_ui (*size, 1);
952 return false;
953 }
954}
955
956
957/* Like gfc_get_array_constructor_element_size, but applied to the whole
958 of array constructor C. */
959
960static bool
961gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
962{
963 gfc_iterator *i;
964 mpz_t val;
965 mpz_t len;
966 bool dynamic;
967
968 mpz_set_ui (*size, 0);
969 mpz_init (len);
970 mpz_init (val);
971
972 dynamic = false;
973 for (; c; c = c->next)
974 {
975 i = c->iterator;
976 if (i && gfc_iterator_has_dynamic_bounds (i))
977 dynamic = true;
978 else
979 {
980 dynamic |= gfc_get_array_constructor_element_size (&len, c->expr);
981 if (i)
982 {
983 /* Multiply the static part of the element size by the
984 number of iterations. */
985 mpz_sub (val, i->end->value.integer, i->start->value.integer);
986 mpz_fdiv_q (val, val, i->step->value.integer);
987 mpz_add_ui (val, val, 1);
988 if (mpz_sgn (val) > 0)
989 mpz_mul (len, len, val);
990 else
991 mpz_set_ui (len, 0);
992 }
993 mpz_add (*size, *size, len);
994 }
995 }
996 mpz_clear (len);
997 mpz_clear (val);
998 return dynamic;
999}
1000
1001
6de9cd9a
DN
1002/* Make sure offset is a variable. */
1003
1004static void
1005gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
1006 tree * offsetvar)
1007{
1008 /* We should have already created the offset variable. We cannot
13413760 1009 create it here because we may be in an inner scope. */
6e45f57b 1010 gcc_assert (*offsetvar != NULL_TREE);
726a989a 1011 gfc_add_modify (pblock, *offsetvar, *poffset);
6de9cd9a
DN
1012 *poffset = *offsetvar;
1013 TREE_USED (*offsetvar) = 1;
1014}
1015
1016
c03fc95d 1017/* Variables needed for bounds-checking. */
32be9f94
PT
1018static bool first_len;
1019static tree first_len_val;
c03fc95d 1020static bool typespec_chararray_ctor;
40f20186
PB
1021
1022static void
ec25720b 1023gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
40f20186
PB
1024 tree offset, gfc_se * se, gfc_expr * expr)
1025{
1026 tree tmp;
40f20186
PB
1027
1028 gfc_conv_expr (se, expr);
1029
1030 /* Store the value. */
38611275 1031 tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
1d6b7f39 1032 tmp = gfc_build_array_ref (tmp, offset, NULL);
32be9f94 1033
40f20186
PB
1034 if (expr->ts.type == BT_CHARACTER)
1035 {
691da334
FXC
1036 int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false);
1037 tree esize;
1038
1039 esize = size_in_bytes (gfc_get_element_type (TREE_TYPE (desc)));
1040 esize = fold_convert (gfc_charlen_type_node, esize);
1041 esize = fold_build2 (TRUNC_DIV_EXPR, gfc_charlen_type_node, esize,
1042 build_int_cst (gfc_charlen_type_node,
1043 gfc_character_kinds[i].bit_size / 8));
1044
40f20186
PB
1045 gfc_conv_string_parameter (se);
1046 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
1047 {
1048 /* The temporary is an array of pointers. */
1049 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
726a989a 1050 gfc_add_modify (&se->pre, tmp, se->expr);
40f20186
PB
1051 }
1052 else
1053 {
1054 /* The temporary is an array of string values. */
d393bbd7 1055 tmp = gfc_build_addr_expr (gfc_get_pchar_type (expr->ts.kind), tmp);
40f20186
PB
1056 /* We know the temporary and the value will be the same length,
1057 so can use memcpy. */
d393bbd7
FXC
1058 gfc_trans_string_copy (&se->pre, esize, tmp, expr->ts.kind,
1059 se->string_length, se->expr, expr->ts.kind);
32be9f94 1060 }
d3d3011f 1061 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !typespec_chararray_ctor)
32be9f94
PT
1062 {
1063 if (first_len)
1064 {
726a989a 1065 gfc_add_modify (&se->pre, first_len_val,
32be9f94
PT
1066 se->string_length);
1067 first_len = false;
1068 }
1069 else
1070 {
1071 /* Verify that all constructor elements are of the same
1072 length. */
1073 tree cond = fold_build2 (NE_EXPR, boolean_type_node,
1074 first_len_val, se->string_length);
1075 gfc_trans_runtime_check
0d52899f 1076 (true, false, cond, &se->pre, &expr->where,
32be9f94
PT
1077 "Different CHARACTER lengths (%ld/%ld) in array constructor",
1078 fold_convert (long_integer_type_node, first_len_val),
1079 fold_convert (long_integer_type_node, se->string_length));
1080 }
40f20186
PB
1081 }
1082 }
1083 else
1084 {
1085 /* TODO: Should the frontend already have done this conversion? */
1086 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
726a989a 1087 gfc_add_modify (&se->pre, tmp, se->expr);
40f20186
PB
1088 }
1089
1090 gfc_add_block_to_block (pblock, &se->pre);
1091 gfc_add_block_to_block (pblock, &se->post);
1092}
1093
1094
ec25720b
RS
1095/* Add the contents of an array to the constructor. DYNAMIC is as for
1096 gfc_trans_array_constructor_value. */
6de9cd9a
DN
1097
1098static void
1099gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
1100 tree type ATTRIBUTE_UNUSED,
ec25720b
RS
1101 tree desc, gfc_expr * expr,
1102 tree * poffset, tree * offsetvar,
1103 bool dynamic)
6de9cd9a
DN
1104{
1105 gfc_se se;
1106 gfc_ss *ss;
1107 gfc_loopinfo loop;
1108 stmtblock_t body;
1109 tree tmp;
ec25720b
RS
1110 tree size;
1111 int n;
6de9cd9a
DN
1112
1113 /* We need this to be a variable so we can increment it. */
1114 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1115
1116 gfc_init_se (&se, NULL);
1117
1118 /* Walk the array expression. */
1119 ss = gfc_walk_expr (expr);
6e45f57b 1120 gcc_assert (ss != gfc_ss_terminator);
6de9cd9a
DN
1121
1122 /* Initialize the scalarizer. */
1123 gfc_init_loopinfo (&loop);
1124 gfc_add_ss_to_loop (&loop, ss);
1125
1126 /* Initialize the loop. */
1127 gfc_conv_ss_startstride (&loop);
bdfd2ff0 1128 gfc_conv_loop_setup (&loop, &expr->where);
6de9cd9a 1129
ec25720b
RS
1130 /* Make sure the constructed array has room for the new data. */
1131 if (dynamic)
1132 {
1133 /* Set SIZE to the total number of elements in the subarray. */
1134 size = gfc_index_one_node;
1135 for (n = 0; n < loop.dimen; n++)
1136 {
1137 tmp = gfc_get_iteration_count (loop.from[n], loop.to[n],
1138 gfc_index_one_node);
1139 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1140 }
1141
1142 /* Grow the constructed array by SIZE elements. */
1143 gfc_grow_array (&loop.pre, desc, size);
1144 }
1145
6de9cd9a
DN
1146 /* Make the loop body. */
1147 gfc_mark_ss_chain_used (ss, 1);
1148 gfc_start_scalarized_body (&loop, &body);
1149 gfc_copy_loopinfo_to_se (&se, &loop);
1150 se.ss = ss;
1151
ec25720b 1152 gfc_trans_array_ctor_element (&body, desc, *poffset, &se, expr);
6e45f57b 1153 gcc_assert (se.ss == gfc_ss_terminator);
6de9cd9a
DN
1154
1155 /* Increment the offset. */
44855d8c
TS
1156 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1157 *poffset, gfc_index_one_node);
726a989a 1158 gfc_add_modify (&body, *poffset, tmp);
6de9cd9a
DN
1159
1160 /* Finish the loop. */
6de9cd9a
DN
1161 gfc_trans_scalarizing_loops (&loop, &body);
1162 gfc_add_block_to_block (&loop.pre, &loop.post);
1163 tmp = gfc_finish_block (&loop.pre);
1164 gfc_add_expr_to_block (pblock, tmp);
1165
1166 gfc_cleanup_loop (&loop);
1167}
1168
1169
ec25720b
RS
1170/* Assign the values to the elements of an array constructor. DYNAMIC
1171 is true if descriptor DESC only contains enough data for the static
1172 size calculated by gfc_get_array_constructor_size. When true, memory
1173 for the dynamic parts must be allocated using realloc. */
6de9cd9a
DN
1174
1175static void
1176gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
ec25720b
RS
1177 tree desc, gfc_constructor * c,
1178 tree * poffset, tree * offsetvar,
1179 bool dynamic)
6de9cd9a
DN
1180{
1181 tree tmp;
6de9cd9a 1182 stmtblock_t body;
6de9cd9a 1183 gfc_se se;
ec25720b 1184 mpz_t size;
6de9cd9a 1185
beb64b4a
DF
1186 tree shadow_loopvar = NULL_TREE;
1187 gfc_saved_var saved_loopvar;
1188
ec25720b 1189 mpz_init (size);
6de9cd9a
DN
1190 for (; c; c = c->next)
1191 {
1192 /* If this is an iterator or an array, the offset must be a variable. */
1193 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
1194 gfc_put_offset_into_var (pblock, poffset, offsetvar);
1195
beb64b4a
DF
1196 /* Shadowing the iterator avoids changing its value and saves us from
1197 keeping track of it. Further, it makes sure that there's always a
1198 backend-decl for the symbol, even if there wasn't one before,
1199 e.g. in the case of an iterator that appears in a specification
1200 expression in an interface mapping. */
1201 if (c->iterator)
1202 {
1203 gfc_symbol *sym = c->iterator->var->symtree->n.sym;
1204 tree type = gfc_typenode_for_spec (&sym->ts);
1205
1206 shadow_loopvar = gfc_create_var (type, "shadow_loopvar");
1207 gfc_shadow_sym (sym, shadow_loopvar, &saved_loopvar);
1208 }
1209
6de9cd9a
DN
1210 gfc_start_block (&body);
1211
1212 if (c->expr->expr_type == EXPR_ARRAY)
1213 {
1214 /* Array constructors can be nested. */
ec25720b 1215 gfc_trans_array_constructor_value (&body, type, desc,
6de9cd9a 1216 c->expr->value.constructor,
ec25720b 1217 poffset, offsetvar, dynamic);
6de9cd9a
DN
1218 }
1219 else if (c->expr->rank > 0)
1220 {
ec25720b
RS
1221 gfc_trans_array_constructor_subarray (&body, type, desc, c->expr,
1222 poffset, offsetvar, dynamic);
6de9cd9a
DN
1223 }
1224 else
1225 {
1226 /* This code really upsets the gimplifier so don't bother for now. */
1227 gfc_constructor *p;
1228 HOST_WIDE_INT n;
1229 HOST_WIDE_INT size;
1230
1231 p = c;
1232 n = 0;
1233 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
1234 {
1235 p = p->next;
1236 n++;
1237 }
1238 if (n < 4)
1239 {
1240 /* Scalar values. */
1241 gfc_init_se (&se, NULL);
ec25720b
RS
1242 gfc_trans_array_ctor_element (&body, desc, *poffset,
1243 &se, c->expr);
6de9cd9a 1244
10c7a96f
SB
1245 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1246 *poffset, gfc_index_one_node);
6de9cd9a
DN
1247 }
1248 else
1249 {
1250 /* Collect multiple scalar constants into a constructor. */
1251 tree list;
1252 tree init;
1253 tree bound;
1254 tree tmptype;
81f5094d 1255 HOST_WIDE_INT idx = 0;
6de9cd9a
DN
1256
1257 p = c;
1258 list = NULL_TREE;
1259 /* Count the number of consecutive scalar constants. */
1260 while (p && !(p->iterator
1261 || p->expr->expr_type != EXPR_CONSTANT))
1262 {
1263 gfc_init_se (&se, NULL);
1264 gfc_conv_constant (&se, p->expr);
d393bbd7 1265
110ea21a
PT
1266 if (c->expr->ts.type != BT_CHARACTER)
1267 se.expr = fold_convert (type, se.expr);
d393bbd7
FXC
1268 /* For constant character array constructors we build
1269 an array of pointers. */
110ea21a 1270 else if (POINTER_TYPE_P (type))
d393bbd7
FXC
1271 se.expr = gfc_build_addr_expr
1272 (gfc_get_pchar_type (p->expr->ts.kind),
1273 se.expr);
1274
81f5094d
JJ
1275 list = tree_cons (build_int_cst (gfc_array_index_type,
1276 idx++), se.expr, list);
6de9cd9a
DN
1277 c = p;
1278 p = p->next;
1279 }
1280
7d60be94 1281 bound = build_int_cst (NULL_TREE, n - 1);
6de9cd9a
DN
1282 /* Create an array type to hold them. */
1283 tmptype = build_range_type (gfc_array_index_type,
7ab92584 1284 gfc_index_zero_node, bound);
6de9cd9a
DN
1285 tmptype = build_array_type (type, tmptype);
1286
4038c495 1287 init = build_constructor_from_list (tmptype, nreverse (list));
6de9cd9a 1288 TREE_CONSTANT (init) = 1;
6de9cd9a
DN
1289 TREE_STATIC (init) = 1;
1290 /* Create a static variable to hold the data. */
1291 tmp = gfc_create_var (tmptype, "data");
1292 TREE_STATIC (tmp) = 1;
1293 TREE_CONSTANT (tmp) = 1;
0f0707d1 1294 TREE_READONLY (tmp) = 1;
6de9cd9a
DN
1295 DECL_INITIAL (tmp) = init;
1296 init = tmp;
1297
1298 /* Use BUILTIN_MEMCPY to assign the values. */
ec25720b 1299 tmp = gfc_conv_descriptor_data_get (desc);
38611275 1300 tmp = build_fold_indirect_ref (tmp);
1d6b7f39 1301 tmp = gfc_build_array_ref (tmp, *poffset, NULL);
628c189e
RG
1302 tmp = gfc_build_addr_expr (NULL_TREE, tmp);
1303 init = gfc_build_addr_expr (NULL_TREE, init);
6de9cd9a
DN
1304
1305 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
7d60be94 1306 bound = build_int_cst (NULL_TREE, n * size);
5039610b
SL
1307 tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
1308 tmp, init, bound);
6de9cd9a
DN
1309 gfc_add_expr_to_block (&body, tmp);
1310
10c7a96f 1311 *poffset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
ac816b02
RG
1312 *poffset,
1313 build_int_cst (gfc_array_index_type, n));
6de9cd9a
DN
1314 }
1315 if (!INTEGER_CST_P (*poffset))
1316 {
726a989a 1317 gfc_add_modify (&body, *offsetvar, *poffset);
6de9cd9a
DN
1318 *poffset = *offsetvar;
1319 }
1320 }
1321
63346ddb 1322 /* The frontend should already have done any expansions
86403f0f
TS
1323 at compile-time. */
1324 if (!c->iterator)
6de9cd9a 1325 {
86403f0f
TS
1326 /* Pass the code as is. */
1327 tmp = gfc_finish_block (&body);
1328 gfc_add_expr_to_block (pblock, tmp);
1329 }
1330 else
1331 {
1332 /* Build the implied do-loop. */
beb64b4a 1333 stmtblock_t implied_do_block;
86403f0f 1334 tree cond;
6de9cd9a
DN
1335 tree end;
1336 tree step;
6de9cd9a 1337 tree exit_label;
86403f0f 1338 tree loopbody;
ec25720b 1339 tree tmp2;
6de9cd9a
DN
1340
1341 loopbody = gfc_finish_block (&body);
1342
beb64b4a
DF
1343 /* Create a new block that holds the implied-do loop. A temporary
1344 loop-variable is used. */
1345 gfc_start_block(&implied_do_block);
bfa7a1e9 1346
13413760 1347 /* Initialize the loop. */
6de9cd9a
DN
1348 gfc_init_se (&se, NULL);
1349 gfc_conv_expr_val (&se, c->iterator->start);
beb64b4a
DF
1350 gfc_add_block_to_block (&implied_do_block, &se.pre);
1351 gfc_add_modify (&implied_do_block, shadow_loopvar, se.expr);
6de9cd9a
DN
1352
1353 gfc_init_se (&se, NULL);
1354 gfc_conv_expr_val (&se, c->iterator->end);
beb64b4a
DF
1355 gfc_add_block_to_block (&implied_do_block, &se.pre);
1356 end = gfc_evaluate_now (se.expr, &implied_do_block);
6de9cd9a
DN
1357
1358 gfc_init_se (&se, NULL);
1359 gfc_conv_expr_val (&se, c->iterator->step);
beb64b4a
DF
1360 gfc_add_block_to_block (&implied_do_block, &se.pre);
1361 step = gfc_evaluate_now (se.expr, &implied_do_block);
6de9cd9a 1362
ec25720b
RS
1363 /* If this array expands dynamically, and the number of iterations
1364 is not constant, we won't have allocated space for the static
1365 part of C->EXPR's size. Do that now. */
1366 if (dynamic && gfc_iterator_has_dynamic_bounds (c->iterator))
1367 {
1368 /* Get the number of iterations. */
beb64b4a 1369 tmp = gfc_get_iteration_count (shadow_loopvar, end, step);
ec25720b
RS
1370
1371 /* Get the static part of C->EXPR's size. */
1372 gfc_get_array_constructor_element_size (&size, c->expr);
1373 tmp2 = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1374
1375 /* Grow the array by TMP * TMP2 elements. */
1376 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, tmp, tmp2);
beb64b4a 1377 gfc_grow_array (&implied_do_block, desc, tmp);
ec25720b
RS
1378 }
1379
6de9cd9a
DN
1380 /* Generate the loop body. */
1381 exit_label = gfc_build_label_decl (NULL_TREE);
1382 gfc_start_block (&body);
1383
86403f0f
TS
1384 /* Generate the exit condition. Depending on the sign of
1385 the step variable we have to generate the correct
1386 comparison. */
1387 tmp = fold_build2 (GT_EXPR, boolean_type_node, step,
1388 build_int_cst (TREE_TYPE (step), 0));
1389 cond = fold_build3 (COND_EXPR, boolean_type_node, tmp,
44855d8c 1390 fold_build2 (GT_EXPR, boolean_type_node,
beb64b4a 1391 shadow_loopvar, end),
44855d8c 1392 fold_build2 (LT_EXPR, boolean_type_node,
beb64b4a 1393 shadow_loopvar, end));
6de9cd9a
DN
1394 tmp = build1_v (GOTO_EXPR, exit_label);
1395 TREE_USED (exit_label) = 1;
86403f0f 1396 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
6de9cd9a
DN
1397 gfc_add_expr_to_block (&body, tmp);
1398
1399 /* The main loop body. */
1400 gfc_add_expr_to_block (&body, loopbody);
1401
86403f0f 1402 /* Increase loop variable by step. */
beb64b4a
DF
1403 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (shadow_loopvar), shadow_loopvar, step);
1404 gfc_add_modify (&body, shadow_loopvar, tmp);
6de9cd9a
DN
1405
1406 /* Finish the loop. */
1407 tmp = gfc_finish_block (&body);
923ab88c 1408 tmp = build1_v (LOOP_EXPR, tmp);
beb64b4a 1409 gfc_add_expr_to_block (&implied_do_block, tmp);
6de9cd9a
DN
1410
1411 /* Add the exit label. */
1412 tmp = build1_v (LABEL_EXPR, exit_label);
beb64b4a
DF
1413 gfc_add_expr_to_block (&implied_do_block, tmp);
1414
1415 /* Finishe the implied-do loop. */
1416 tmp = gfc_finish_block(&implied_do_block);
1417 gfc_add_expr_to_block(pblock, tmp);
bfa7a1e9 1418
beb64b4a 1419 gfc_restore_sym (c->iterator->var->symtree->n.sym, &saved_loopvar);
6de9cd9a 1420 }
6de9cd9a 1421 }
ec25720b 1422 mpz_clear (size);
6de9cd9a
DN
1423}
1424
1425
40f20186
PB
1426/* Figure out the string length of a variable reference expression.
1427 Used by get_array_ctor_strlen. */
1428
1429static void
1430get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1431{
1432 gfc_ref *ref;
1433 gfc_typespec *ts;
1855915a 1434 mpz_t char_len;
40f20186
PB
1435
1436 /* Don't bother if we already know the length is a constant. */
1437 if (*len && INTEGER_CST_P (*len))
1438 return;
1439
1440 ts = &expr->symtree->n.sym->ts;
1441 for (ref = expr->ref; ref; ref = ref->next)
1442 {
1443 switch (ref->type)
1444 {
1445 case REF_ARRAY:
df7df328 1446 /* Array references don't change the string length. */
40f20186
PB
1447 break;
1448
0e3e65bc 1449 case REF_COMPONENT:
f7b529fa 1450 /* Use the length of the component. */
40f20186
PB
1451 ts = &ref->u.c.component->ts;
1452 break;
1453
1855915a
PT
1454 case REF_SUBSTRING:
1455 if (ref->u.ss.start->expr_type != EXPR_CONSTANT
08ddab21 1456 || ref->u.ss.end->expr_type != EXPR_CONSTANT)
1855915a
PT
1457 break;
1458 mpz_init_set_ui (char_len, 1);
1459 mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
1460 mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
d393bbd7 1461 *len = gfc_conv_mpz_to_tree (char_len, gfc_default_integer_kind);
1855915a
PT
1462 *len = convert (gfc_charlen_type_node, *len);
1463 mpz_clear (char_len);
1464 return;
1465
40f20186
PB
1466 default:
1467 /* TODO: Substrings are tricky because we can't evaluate the
1468 expression more than once. For now we just give up, and hope
1469 we can figure it out elsewhere. */
1470 return;
1471 }
1472 }
1473
1474 *len = ts->cl->backend_decl;
1475}
1476
1477
0ee8e250
PT
1478/* A catch-all to obtain the string length for anything that is not a
1479 constant, array or variable. */
1480static void
1481get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
1482{
1483 gfc_se se;
1484 gfc_ss *ss;
1485
1486 /* Don't bother if we already know the length is a constant. */
1487 if (*len && INTEGER_CST_P (*len))
1488 return;
1489
07368af0 1490 if (!e->ref && e->ts.cl && e->ts.cl->length
0ee8e250
PT
1491 && e->ts.cl->length->expr_type == EXPR_CONSTANT)
1492 {
1493 /* This is easy. */
1494 gfc_conv_const_charlen (e->ts.cl);
1495 *len = e->ts.cl->backend_decl;
1496 }
1497 else
1498 {
1499 /* Otherwise, be brutal even if inefficient. */
1500 ss = gfc_walk_expr (e);
1501 gfc_init_se (&se, NULL);
1502
1503 /* No function call, in case of side effects. */
1504 se.no_function_call = 1;
1505 if (ss == gfc_ss_terminator)
1506 gfc_conv_expr (&se, e);
1507 else
1508 gfc_conv_expr_descriptor (&se, e, ss);
1509
1510 /* Fix the value. */
1511 *len = gfc_evaluate_now (se.string_length, &se.pre);
1512
1513 gfc_add_block_to_block (block, &se.pre);
1514 gfc_add_block_to_block (block, &se.post);
1515
1516 e->ts.cl->backend_decl = *len;
1517 }
1518}
1519
1520
40f20186 1521/* Figure out the string length of a character array constructor.
88fec49f
DK
1522 If len is NULL, don't calculate the length; this happens for recursive calls
1523 when a sub-array-constructor is an element but not at the first position,
1524 so when we're not interested in the length.
40f20186
PB
1525 Returns TRUE if all elements are character constants. */
1526
636da744 1527bool
0ee8e250 1528get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
40f20186
PB
1529{
1530 bool is_const;
1531
1532 is_const = TRUE;
58fbb917
PT
1533
1534 if (c == NULL)
1535 {
88fec49f
DK
1536 if (len)
1537 *len = build_int_cstu (gfc_charlen_type_node, 0);
58fbb917
PT
1538 return is_const;
1539 }
1540
88fec49f
DK
1541 /* Loop over all constructor elements to find out is_const, but in len we
1542 want to store the length of the first, not the last, element. We can
1543 of course exit the loop as soon as is_const is found to be false. */
1544 for (; c && is_const; c = c->next)
40f20186
PB
1545 {
1546 switch (c->expr->expr_type)
1547 {
1548 case EXPR_CONSTANT:
88fec49f 1549 if (len && !(*len && INTEGER_CST_P (*len)))
d7177ab2 1550 *len = build_int_cstu (gfc_charlen_type_node,
40f20186
PB
1551 c->expr->value.character.length);
1552 break;
1553
1554 case EXPR_ARRAY:
0ee8e250 1555 if (!get_array_ctor_strlen (block, c->expr->value.constructor, len))
01201992 1556 is_const = false;
40f20186
PB
1557 break;
1558
1559 case EXPR_VARIABLE:
1560 is_const = false;
88fec49f
DK
1561 if (len)
1562 get_array_ctor_var_strlen (c->expr, len);
40f20186
PB
1563 break;
1564
1565 default:
01201992 1566 is_const = false;
88fec49f
DK
1567 if (len)
1568 get_array_ctor_all_strlen (block, c->expr, len);
40f20186
PB
1569 break;
1570 }
88fec49f
DK
1571
1572 /* After the first iteration, we don't want the length modified. */
1573 len = NULL;
40f20186
PB
1574 }
1575
1576 return is_const;
1577}
1578
62511fb1
RS
1579/* Check whether the array constructor C consists entirely of constant
1580 elements, and if so returns the number of those elements, otherwise
1581 return zero. Note, an empty or NULL array constructor returns zero. */
1582
b01e2f88
RS
1583unsigned HOST_WIDE_INT
1584gfc_constant_array_constructor_p (gfc_constructor * c)
62511fb1
RS
1585{
1586 unsigned HOST_WIDE_INT nelem = 0;
1587
1588 while (c)
1589 {
1590 if (c->iterator
1591 || c->expr->rank > 0
1592 || c->expr->expr_type != EXPR_CONSTANT)
1593 return 0;
1594 c = c->next;
1595 nelem++;
1596 }
1597 return nelem;
1598}
1599
1600
1601/* Given EXPR, the constant array constructor specified by an EXPR_ARRAY,
1602 and the tree type of it's elements, TYPE, return a static constant
1603 variable that is compile-time initialized. */
1604
b01e2f88 1605tree
62511fb1
RS
1606gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
1607{
1608 tree tmptype, list, init, tmp;
1609 HOST_WIDE_INT nelem;
1610 gfc_constructor *c;
1611 gfc_array_spec as;
1612 gfc_se se;
61a04b5b 1613 int i;
62511fb1
RS
1614
1615 /* First traverse the constructor list, converting the constants
1616 to tree to build an initializer. */
1617 nelem = 0;
1618 list = NULL_TREE;
1619 c = expr->value.constructor;
1620 while (c)
1621 {
1622 gfc_init_se (&se, NULL);
1623 gfc_conv_constant (&se, c->expr);
110ea21a
PT
1624 if (c->expr->ts.type != BT_CHARACTER)
1625 se.expr = fold_convert (type, se.expr);
1626 else if (POINTER_TYPE_P (type))
d393bbd7
FXC
1627 se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
1628 se.expr);
81f5094d
JJ
1629 list = tree_cons (build_int_cst (gfc_array_index_type, nelem),
1630 se.expr, list);
62511fb1
RS
1631 c = c->next;
1632 nelem++;
1633 }
1634
65de695f 1635 /* Next determine the tree type for the array. We use the gfortran
62511fb1
RS
1636 front-end's gfc_get_nodesc_array_type in order to create a suitable
1637 GFC_ARRAY_TYPE_P that may be used by the scalarizer. */
1638
1639 memset (&as, 0, sizeof (gfc_array_spec));
1640
61a04b5b 1641 as.rank = expr->rank;
62511fb1 1642 as.type = AS_EXPLICIT;
61a04b5b
RS
1643 if (!expr->shape)
1644 {
1645 as.lower[0] = gfc_int_expr (0);
1646 as.upper[0] = gfc_int_expr (nelem - 1);
1647 }
1648 else
1649 for (i = 0; i < expr->rank; i++)
1650 {
1651 int tmp = (int) mpz_get_si (expr->shape[i]);
1652 as.lower[i] = gfc_int_expr (0);
1653 as.upper[i] = gfc_int_expr (tmp - 1);
1654 }
1655
dcfef7d4 1656 tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
62511fb1
RS
1657
1658 init = build_constructor_from_list (tmptype, nreverse (list));
1659
1660 TREE_CONSTANT (init) = 1;
62511fb1
RS
1661 TREE_STATIC (init) = 1;
1662
1663 tmp = gfc_create_var (tmptype, "A");
1664 TREE_STATIC (tmp) = 1;
1665 TREE_CONSTANT (tmp) = 1;
62511fb1
RS
1666 TREE_READONLY (tmp) = 1;
1667 DECL_INITIAL (tmp) = init;
1668
1669 return tmp;
1670}
1671
1672
1673/* Translate a constant EXPR_ARRAY array constructor for the scalarizer.
1674 This mostly initializes the scalarizer state info structure with the
1675 appropriate values to directly use the array created by the function
1676 gfc_build_constant_array_constructor. */
1677
1678static void
1679gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
1680 gfc_ss * ss, tree type)
1681{
1682 gfc_ss_info *info;
1683 tree tmp;
61a04b5b 1684 int i;
62511fb1
RS
1685
1686 tmp = gfc_build_constant_array_constructor (ss->expr, type);
1687
1688 info = &ss->data.info;
1689
1690 info->descriptor = tmp;
628c189e 1691 info->data = gfc_build_addr_expr (NULL_TREE, tmp);
45bc572c 1692 info->offset = gfc_index_zero_node;
62511fb1 1693
61a04b5b
RS
1694 for (i = 0; i < info->dimen; i++)
1695 {
1696 info->delta[i] = gfc_index_zero_node;
1697 info->start[i] = gfc_index_zero_node;
1698 info->end[i] = gfc_index_zero_node;
1699 info->stride[i] = gfc_index_one_node;
1700 info->dim[i] = i;
1701 }
62511fb1
RS
1702
1703 if (info->dimen > loop->temp_dim)
1704 loop->temp_dim = info->dimen;
1705}
1706
61a04b5b
RS
1707/* Helper routine of gfc_trans_array_constructor to determine if the
1708 bounds of the loop specified by LOOP are constant and simple enough
1709 to use with gfc_trans_constant_array_constructor. Returns the
df2fba9e 1710 iteration count of the loop if suitable, and NULL_TREE otherwise. */
61a04b5b
RS
1711
1712static tree
1713constant_array_constructor_loop_size (gfc_loopinfo * loop)
1714{
1715 tree size = gfc_index_one_node;
1716 tree tmp;
1717 int i;
1718
1719 for (i = 0; i < loop->dimen; i++)
1720 {
1721 /* If the bounds aren't constant, return NULL_TREE. */
1722 if (!INTEGER_CST_P (loop->from[i]) || !INTEGER_CST_P (loop->to[i]))
1723 return NULL_TREE;
1724 if (!integer_zerop (loop->from[i]))
1725 {
86bf520d 1726 /* Only allow nonzero "from" in one-dimensional arrays. */
61a04b5b
RS
1727 if (loop->dimen != 1)
1728 return NULL_TREE;
1729 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1730 loop->to[i], loop->from[i]);
1731 }
1732 else
1733 tmp = loop->to[i];
1734 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1735 tmp, gfc_index_one_node);
1736 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1737 }
1738
1739 return size;
1740}
1741
40f20186 1742
6de9cd9a
DN
1743/* Array constructors are handled by constructing a temporary, then using that
1744 within the scalarization loop. This is not optimal, but seems by far the
1745 simplest method. */
1746
1747static void
bdfd2ff0 1748gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
6de9cd9a 1749{
ec25720b 1750 gfc_constructor *c;
6de9cd9a
DN
1751 tree offset;
1752 tree offsetvar;
1753 tree desc;
6de9cd9a 1754 tree type;
ec25720b 1755 bool dynamic;
4b7f8314
DK
1756 bool old_first_len, old_typespec_chararray_ctor;
1757 tree old_first_len_val;
1758
1759 /* Save the old values for nested checking. */
1760 old_first_len = first_len;
1761 old_first_len_val = first_len_val;
1762 old_typespec_chararray_ctor = typespec_chararray_ctor;
6de9cd9a 1763
c03fc95d
DK
1764 /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
1765 typespec was given for the array constructor. */
1766 typespec_chararray_ctor = (ss->expr->ts.cl
1767 && ss->expr->ts.cl->length_from_typespec);
1768
d3d3011f
FXC
1769 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1770 && ss->expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
32be9f94
PT
1771 {
1772 first_len_val = gfc_create_var (gfc_charlen_type_node, "len");
1773 first_len = true;
1774 }
1775
6de9cd9a 1776 ss->data.info.dimen = loop->dimen;
40f20186 1777
ec25720b 1778 c = ss->expr->value.constructor;
40f20186
PB
1779 if (ss->expr->ts.type == BT_CHARACTER)
1780 {
c03fc95d
DK
1781 bool const_string;
1782
1783 /* get_array_ctor_strlen walks the elements of the constructor, if a
1784 typespec was given, we already know the string length and want the one
1785 specified there. */
1786 if (typespec_chararray_ctor && ss->expr->ts.cl->length
1787 && ss->expr->ts.cl->length->expr_type != EXPR_CONSTANT)
1788 {
1789 gfc_se length_se;
1790
1791 const_string = false;
1792 gfc_init_se (&length_se, NULL);
1793 gfc_conv_expr_type (&length_se, ss->expr->ts.cl->length,
1794 gfc_charlen_type_node);
1795 ss->string_length = length_se.expr;
1796 gfc_add_block_to_block (&loop->pre, &length_se.pre);
1797 gfc_add_block_to_block (&loop->post, &length_se.post);
1798 }
1799 else
1800 const_string = get_array_ctor_strlen (&loop->pre, c,
1801 &ss->string_length);
ca39e6f2
FXC
1802
1803 /* Complex character array constructors should have been taken care of
1804 and not end up here. */
1805 gcc_assert (ss->string_length);
40f20186 1806
ac5753b7 1807 ss->expr->ts.cl->backend_decl = ss->string_length;
0ee8e250 1808
40f20186
PB
1809 type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1810 if (const_string)
1811 type = build_pointer_type (type);
1812 }
1813 else
62511fb1 1814 type = gfc_typenode_for_spec (&ss->expr->ts);
40f20186 1815
ec25720b
RS
1816 /* See if the constructor determines the loop bounds. */
1817 dynamic = false;
6a56381b
PT
1818
1819 if (ss->expr->shape && loop->dimen > 1 && loop->to[0] == NULL_TREE)
1820 {
1821 /* We have a multidimensional parameter. */
1822 int n;
1823 for (n = 0; n < ss->expr->rank; n++)
1824 {
1825 loop->from[n] = gfc_index_zero_node;
1826 loop->to[n] = gfc_conv_mpz_to_tree (ss->expr->shape [n],
1827 gfc_index_integer_kind);
1828 loop->to[n] = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1829 loop->to[n], gfc_index_one_node);
1830 }
1831 }
1832
ec25720b
RS
1833 if (loop->to[0] == NULL_TREE)
1834 {
1835 mpz_t size;
1836
1837 /* We should have a 1-dimensional, zero-based loop. */
1838 gcc_assert (loop->dimen == 1);
1839 gcc_assert (integer_zerop (loop->from[0]));
1840
1841 /* Split the constructor size into a static part and a dynamic part.
1842 Allocate the static size up-front and record whether the dynamic
1843 size might be nonzero. */
1844 mpz_init (size);
1845 dynamic = gfc_get_array_constructor_size (&size, c);
1846 mpz_sub_ui (size, size, 1);
1847 loop->to[0] = gfc_conv_mpz_to_tree (size, gfc_index_integer_kind);
1848 mpz_clear (size);
1849 }
1850
62511fb1 1851 /* Special case constant array constructors. */
61a04b5b 1852 if (!dynamic)
62511fb1 1853 {
b01e2f88 1854 unsigned HOST_WIDE_INT nelem = gfc_constant_array_constructor_p (c);
62511fb1
RS
1855 if (nelem > 0)
1856 {
61a04b5b
RS
1857 tree size = constant_array_constructor_loop_size (loop);
1858 if (size && compare_tree_int (size, nelem) == 0)
62511fb1
RS
1859 {
1860 gfc_trans_constant_array_constructor (loop, ss, type);
4b7f8314 1861 goto finish;
62511fb1
RS
1862 }
1863 }
1864 }
1865
8e119f1b 1866 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop, &ss->data.info,
12f681a0 1867 type, NULL_TREE, dynamic, true, false, where);
6de9cd9a
DN
1868
1869 desc = ss->data.info.descriptor;
7ab92584 1870 offset = gfc_index_zero_node;
6de9cd9a 1871 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
01306727 1872 TREE_NO_WARNING (offsetvar) = 1;
6de9cd9a 1873 TREE_USED (offsetvar) = 0;
ec25720b
RS
1874 gfc_trans_array_constructor_value (&loop->pre, type, desc, c,
1875 &offset, &offsetvar, dynamic);
1876
1877 /* If the array grows dynamically, the upper bound of the loop variable
1878 is determined by the array's final upper bound. */
1879 if (dynamic)
1880 loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
6de9cd9a
DN
1881
1882 if (TREE_USED (offsetvar))
1883 pushdecl (offsetvar);
1884 else
6e45f57b 1885 gcc_assert (INTEGER_CST_P (offset));
6de9cd9a 1886#if 0
dfc46c1f 1887 /* Disable bound checking for now because it's probably broken. */
d3d3011f 1888 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
6de9cd9a 1889 {
6e45f57b 1890 gcc_unreachable ();
6de9cd9a
DN
1891 }
1892#endif
4b7f8314
DK
1893
1894finish:
1895 /* Restore old values of globals. */
1896 first_len = old_first_len;
1897 first_len_val = old_first_len_val;
1898 typespec_chararray_ctor = old_typespec_chararray_ctor;
6de9cd9a
DN
1899}
1900
1901
7a70c12d
RS
1902/* INFO describes a GFC_SS_SECTION in loop LOOP, and this function is
1903 called after evaluating all of INFO's vector dimensions. Go through
1904 each such vector dimension and see if we can now fill in any missing
1905 loop bounds. */
1906
1907static void
1908gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
1909{
1910 gfc_se se;
1911 tree tmp;
1912 tree desc;
1913 tree zero;
1914 int n;
1915 int dim;
1916
1917 for (n = 0; n < loop->dimen; n++)
1918 {
1919 dim = info->dim[n];
1920 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
1921 && loop->to[n] == NULL)
1922 {
1923 /* Loop variable N indexes vector dimension DIM, and we don't
1924 yet know the upper bound of loop variable N. Set it to the
1925 difference between the vector's upper and lower bounds. */
1926 gcc_assert (loop->from[n] == gfc_index_zero_node);
1927 gcc_assert (info->subscript[dim]
1928 && info->subscript[dim]->type == GFC_SS_VECTOR);
1929
1930 gfc_init_se (&se, NULL);
1931 desc = info->subscript[dim]->data.info.descriptor;
1932 zero = gfc_rank_cst[0];
1933 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1934 gfc_conv_descriptor_ubound (desc, zero),
1935 gfc_conv_descriptor_lbound (desc, zero));
1936 tmp = gfc_evaluate_now (tmp, &loop->pre);
1937 loop->to[n] = tmp;
1938 }
1939 }
1940}
1941
1942
6de9cd9a
DN
1943/* Add the pre and post chains for all the scalar expressions in a SS chain
1944 to loop. This is called after the loop parameters have been calculated,
1945 but before the actual scalarizing loops. */
6de9cd9a
DN
1946
1947static void
bdfd2ff0
TK
1948gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
1949 locus * where)
6de9cd9a
DN
1950{
1951 gfc_se se;
1952 int n;
1953
df2fba9e
RW
1954 /* TODO: This can generate bad code if there are ordering dependencies,
1955 e.g., a callee allocated function and an unknown size constructor. */
6e45f57b 1956 gcc_assert (ss != NULL);
6de9cd9a
DN
1957
1958 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
1959 {
6e45f57b 1960 gcc_assert (ss);
6de9cd9a
DN
1961
1962 switch (ss->type)
1963 {
1964 case GFC_SS_SCALAR:
1965 /* Scalar expression. Evaluate this now. This includes elemental
1966 dimension indices, but not array section bounds. */
1967 gfc_init_se (&se, NULL);
ae772c2d
PT
1968 gfc_conv_expr (&se, ss->expr);
1969 gfc_add_block_to_block (&loop->pre, &se.pre);
6de9cd9a 1970
ae772c2d
PT
1971 if (ss->expr->ts.type != BT_CHARACTER)
1972 {
1973 /* Move the evaluation of scalar expressions outside the
1974 scalarization loop, except for WHERE assignments. */
1975 if (subscript)
1976 se.expr = convert(gfc_array_index_type, se.expr);
1977 if (!ss->where)
1978 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
1979 gfc_add_block_to_block (&loop->pre, &se.post);
1980 }
1981 else
1982 gfc_add_block_to_block (&loop->post, &se.post);
6de9cd9a
DN
1983
1984 ss->data.scalar.expr = se.expr;
40f20186 1985 ss->string_length = se.string_length;
6de9cd9a
DN
1986 break;
1987
1988 case GFC_SS_REFERENCE:
1989 /* Scalar reference. Evaluate this now. */
1990 gfc_init_se (&se, NULL);
1991 gfc_conv_expr_reference (&se, ss->expr);
1992 gfc_add_block_to_block (&loop->pre, &se.pre);
1993 gfc_add_block_to_block (&loop->post, &se.post);
1994
1995 ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
40f20186 1996 ss->string_length = se.string_length;
6de9cd9a
DN
1997 break;
1998
1999 case GFC_SS_SECTION:
7a70c12d 2000 /* Add the expressions for scalar and vector subscripts. */
6de9cd9a 2001 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
7a70c12d 2002 if (ss->data.info.subscript[n])
bdfd2ff0
TK
2003 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true,
2004 where);
7a70c12d
RS
2005
2006 gfc_set_vector_loop_bounds (loop, &ss->data.info);
2007 break;
2008
2009 case GFC_SS_VECTOR:
2010 /* Get the vector's descriptor and store it in SS. */
2011 gfc_init_se (&se, NULL);
2012 gfc_conv_expr_descriptor (&se, ss->expr, gfc_walk_expr (ss->expr));
2013 gfc_add_block_to_block (&loop->pre, &se.pre);
2014 gfc_add_block_to_block (&loop->post, &se.post);
2015 ss->data.info.descriptor = se.expr;
6de9cd9a
DN
2016 break;
2017
2018 case GFC_SS_INTRINSIC:
2019 gfc_add_intrinsic_ss_code (loop, ss);
2020 break;
2021
2022 case GFC_SS_FUNCTION:
2023 /* Array function return value. We call the function and save its
2024 result in a temporary for use inside the loop. */
2025 gfc_init_se (&se, NULL);
2026 se.loop = loop;
2027 se.ss = ss;
2028 gfc_conv_expr (&se, ss->expr);
2029 gfc_add_block_to_block (&loop->pre, &se.pre);
2030 gfc_add_block_to_block (&loop->post, &se.post);
0348d6fd 2031 ss->string_length = se.string_length;
6de9cd9a
DN
2032 break;
2033
2034 case GFC_SS_CONSTRUCTOR:
f2d3cb25 2035 if (ss->expr->ts.type == BT_CHARACTER
fe8edd0c 2036 && ss->string_length == NULL
f2d3cb25
PT
2037 && ss->expr->ts.cl
2038 && ss->expr->ts.cl->length)
2039 {
2040 gfc_init_se (&se, NULL);
2041 gfc_conv_expr_type (&se, ss->expr->ts.cl->length,
2042 gfc_charlen_type_node);
2043 ss->string_length = se.expr;
2044 gfc_add_block_to_block (&loop->pre, &se.pre);
2045 gfc_add_block_to_block (&loop->post, &se.post);
2046 }
bdfd2ff0 2047 gfc_trans_array_constructor (loop, ss, where);
6de9cd9a
DN
2048 break;
2049
fc90a8f2 2050 case GFC_SS_TEMP:
e9cfef64
PB
2051 case GFC_SS_COMPONENT:
2052 /* Do nothing. These are handled elsewhere. */
fc90a8f2
PB
2053 break;
2054
6de9cd9a 2055 default:
6e45f57b 2056 gcc_unreachable ();
6de9cd9a
DN
2057 }
2058 }
2059}
2060
2061
2062/* Translate expressions for the descriptor and data pointer of a SS. */
2063/*GCC ARRAYS*/
2064
2065static void
2066gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
2067{
2068 gfc_se se;
2069 tree tmp;
2070
2071 /* Get the descriptor for the array to be scalarized. */
6e45f57b 2072 gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
2073 gfc_init_se (&se, NULL);
2074 se.descriptor_only = 1;
2075 gfc_conv_expr_lhs (&se, ss->expr);
2076 gfc_add_block_to_block (block, &se.pre);
2077 ss->data.info.descriptor = se.expr;
40f20186 2078 ss->string_length = se.string_length;
6de9cd9a
DN
2079
2080 if (base)
2081 {
2082 /* Also the data pointer. */
2083 tmp = gfc_conv_array_data (se.expr);
2084 /* If this is a variable or address of a variable we use it directly.
2054fc29 2085 Otherwise we must evaluate it now to avoid breaking dependency
6de9cd9a
DN
2086 analysis by pulling the expressions for elemental array indices
2087 inside the loop. */
2088 if (!(DECL_P (tmp)
2089 || (TREE_CODE (tmp) == ADDR_EXPR
2090 && DECL_P (TREE_OPERAND (tmp, 0)))))
2091 tmp = gfc_evaluate_now (tmp, block);
2092 ss->data.info.data = tmp;
2093
2094 tmp = gfc_conv_array_offset (se.expr);
2095 ss->data.info.offset = gfc_evaluate_now (tmp, block);
2096 }
2097}
2098
2099
1f2959f0 2100/* Initialize a gfc_loopinfo structure. */
6de9cd9a
DN
2101
2102void
2103gfc_init_loopinfo (gfc_loopinfo * loop)
2104{
2105 int n;
2106
2107 memset (loop, 0, sizeof (gfc_loopinfo));
2108 gfc_init_block (&loop->pre);
2109 gfc_init_block (&loop->post);
2110
13413760 2111 /* Initially scalarize in order. */
6de9cd9a
DN
2112 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
2113 loop->order[n] = n;
2114
2115 loop->ss = gfc_ss_terminator;
2116}
2117
2118
e7dc5b4f 2119/* Copies the loop variable info to a gfc_se structure. Does not copy the SS
6de9cd9a
DN
2120 chain. */
2121
2122void
2123gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
2124{
2125 se->loop = loop;
2126}
2127
2128
2129/* Return an expression for the data pointer of an array. */
2130
2131tree
2132gfc_conv_array_data (tree descriptor)
2133{
2134 tree type;
2135
2136 type = TREE_TYPE (descriptor);
2137 if (GFC_ARRAY_TYPE_P (type))
2138 {
2139 if (TREE_CODE (type) == POINTER_TYPE)
2140 return descriptor;
2141 else
2142 {
13413760 2143 /* Descriptorless arrays. */
628c189e 2144 return gfc_build_addr_expr (NULL_TREE, descriptor);
6de9cd9a
DN
2145 }
2146 }
2147 else
4c73896d 2148 return gfc_conv_descriptor_data_get (descriptor);
6de9cd9a
DN
2149}
2150
2151
2152/* Return an expression for the base offset of an array. */
2153
2154tree
2155gfc_conv_array_offset (tree descriptor)
2156{
2157 tree type;
2158
2159 type = TREE_TYPE (descriptor);
2160 if (GFC_ARRAY_TYPE_P (type))
2161 return GFC_TYPE_ARRAY_OFFSET (type);
2162 else
2163 return gfc_conv_descriptor_offset (descriptor);
2164}
2165
2166
2167/* Get an expression for the array stride. */
2168
2169tree
2170gfc_conv_array_stride (tree descriptor, int dim)
2171{
2172 tree tmp;
2173 tree type;
2174
2175 type = TREE_TYPE (descriptor);
2176
2177 /* For descriptorless arrays use the array size. */
2178 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
2179 if (tmp != NULL_TREE)
2180 return tmp;
2181
2182 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
2183 return tmp;
2184}
2185
2186
2187/* Like gfc_conv_array_stride, but for the lower bound. */
2188
2189tree
2190gfc_conv_array_lbound (tree descriptor, int dim)
2191{
2192 tree tmp;
2193 tree type;
2194
2195 type = TREE_TYPE (descriptor);
2196
2197 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
2198 if (tmp != NULL_TREE)
2199 return tmp;
2200
2201 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
2202 return tmp;
2203}
2204
2205
2206/* Like gfc_conv_array_stride, but for the upper bound. */
2207
2208tree
2209gfc_conv_array_ubound (tree descriptor, int dim)
2210{
2211 tree tmp;
2212 tree type;
2213
2214 type = TREE_TYPE (descriptor);
2215
2216 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
2217 if (tmp != NULL_TREE)
2218 return tmp;
2219
2220 /* This should only ever happen when passing an assumed shape array
2221 as an actual parameter. The value will never be used. */
2222 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
7ab92584 2223 return gfc_index_zero_node;
6de9cd9a
DN
2224
2225 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
2226 return tmp;
2227}
2228
2229
6de9cd9a
DN
2230/* Generate code to perform an array index bound check. */
2231
2232static tree
d16b57df 2233gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
c099916d 2234 locus * where, bool check_upper)
6de9cd9a 2235{
6de9cd9a
DN
2236 tree fault;
2237 tree tmp;
dd18a33b 2238 char *msg;
d19c0f4f 2239 const char * name = NULL;
6de9cd9a 2240
d3d3011f 2241 if (!(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS))
6de9cd9a
DN
2242 return index;
2243
2244 index = gfc_evaluate_now (index, &se->pre);
dd18a33b 2245
d19c0f4f
FXC
2246 /* We find a name for the error message. */
2247 if (se->ss)
2248 name = se->ss->expr->symtree->name;
2249
2250 if (!name && se->loop && se->loop->ss && se->loop->ss->expr
2251 && se->loop->ss->expr->symtree)
2252 name = se->loop->ss->expr->symtree->name;
2253
2254 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2255 && se->loop->ss->loop_chain->expr
2256 && se->loop->ss->loop_chain->expr->symtree)
2257 name = se->loop->ss->loop_chain->expr->symtree->name;
2258
2259 if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
2260 && se->loop->ss->loop_chain->expr->symtree)
2261 name = se->loop->ss->loop_chain->expr->symtree->name;
2262
2263 if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
2264 {
2265 if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
2266 && se->loop->ss->expr->value.function.name)
2267 name = se->loop->ss->expr->value.function.name;
2268 else
2269 if (se->loop->ss->type == GFC_SS_CONSTRUCTOR
2270 || se->loop->ss->type == GFC_SS_SCALAR)
2271 name = "unnamed constant";
2272 }
2273
6de9cd9a
DN
2274 /* Check lower bound. */
2275 tmp = gfc_conv_array_lbound (descriptor, n);
10c7a96f 2276 fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
d19c0f4f 2277 if (name)
1954a27b
TB
2278 asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
2279 "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
dd18a33b 2280 else
1954a27b
TB
2281 asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
2282 gfc_msg_fault, n+1);
0d52899f 2283 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
c8fe94c7
FXC
2284 fold_convert (long_integer_type_node, index),
2285 fold_convert (long_integer_type_node, tmp));
dd18a33b
FXC
2286 gfc_free (msg);
2287
6de9cd9a 2288 /* Check upper bound. */
c099916d
FXC
2289 if (check_upper)
2290 {
2291 tmp = gfc_conv_array_ubound (descriptor, n);
2292 fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
2293 if (name)
2294 asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
1954a27b 2295 " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
c099916d 2296 else
1954a27b
TB
2297 asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
2298 gfc_msg_fault, n+1);
0d52899f 2299 gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
c8fe94c7
FXC
2300 fold_convert (long_integer_type_node, index),
2301 fold_convert (long_integer_type_node, tmp));
c099916d
FXC
2302 gfc_free (msg);
2303 }
6de9cd9a
DN
2304
2305 return index;
2306}
2307
2308
6de9cd9a 2309/* Return the offset for an index. Performs bound checking for elemental
e7dc5b4f 2310 dimensions. Single element references are processed separately. */
6de9cd9a
DN
2311
2312static tree
2313gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
2314 gfc_array_ref * ar, tree stride)
2315{
2316 tree index;
7a70c12d
RS
2317 tree desc;
2318 tree data;
6de9cd9a
DN
2319
2320 /* Get the index into the array for this dimension. */
2321 if (ar)
2322 {
6e45f57b 2323 gcc_assert (ar->type != AR_ELEMENT);
7a70c12d 2324 switch (ar->dimen_type[dim])
6de9cd9a 2325 {
7a70c12d 2326 case DIMEN_ELEMENT:
6de9cd9a 2327 /* Elemental dimension. */
6e45f57b 2328 gcc_assert (info->subscript[dim]
7a70c12d 2329 && info->subscript[dim]->type == GFC_SS_SCALAR);
6de9cd9a
DN
2330 /* We've already translated this value outside the loop. */
2331 index = info->subscript[dim]->data.scalar.expr;
2332
c099916d
FXC
2333 index = gfc_trans_array_bound_check (se, info->descriptor,
2334 index, dim, &ar->where,
2335 (ar->as->type != AS_ASSUMED_SIZE
2336 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
7a70c12d
RS
2337 break;
2338
2339 case DIMEN_VECTOR:
2340 gcc_assert (info && se->loop);
2341 gcc_assert (info->subscript[dim]
2342 && info->subscript[dim]->type == GFC_SS_VECTOR);
2343 desc = info->subscript[dim]->data.info.descriptor;
2344
2345 /* Get a zero-based index into the vector. */
2346 index = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2347 se->loop->loopvar[i], se->loop->from[i]);
2348
2349 /* Multiply the index by the stride. */
2350 index = fold_build2 (MULT_EXPR, gfc_array_index_type,
2351 index, gfc_conv_array_stride (desc, 0));
2352
2353 /* Read the vector to get an index into info->descriptor. */
38611275 2354 data = build_fold_indirect_ref (gfc_conv_array_data (desc));
1d6b7f39 2355 index = gfc_build_array_ref (data, index, NULL);
7a70c12d
RS
2356 index = gfc_evaluate_now (index, &se->pre);
2357
2358 /* Do any bounds checking on the final info->descriptor index. */
c099916d
FXC
2359 index = gfc_trans_array_bound_check (se, info->descriptor,
2360 index, dim, &ar->where,
2361 (ar->as->type != AS_ASSUMED_SIZE
2362 && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
7a70c12d
RS
2363 break;
2364
2365 case DIMEN_RANGE:
6de9cd9a 2366 /* Scalarized dimension. */
6e45f57b 2367 gcc_assert (info && se->loop);
6de9cd9a 2368
df7df328 2369 /* Multiply the loop variable by the stride and delta. */
6de9cd9a 2370 index = se->loop->loopvar[i];
ecc54e6e
RS
2371 if (!integer_onep (info->stride[i]))
2372 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index,
2373 info->stride[i]);
2374 if (!integer_zerop (info->delta[i]))
2375 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index,
2376 info->delta[i]);
7a70c12d 2377 break;
6de9cd9a 2378
7a70c12d
RS
2379 default:
2380 gcc_unreachable ();
6de9cd9a
DN
2381 }
2382 }
2383 else
2384 {
e9cfef64 2385 /* Temporary array or derived type component. */
6e45f57b 2386 gcc_assert (se->loop);
6de9cd9a 2387 index = se->loop->loopvar[se->loop->order[i]];
e9cfef64 2388 if (!integer_zerop (info->delta[i]))
10c7a96f
SB
2389 index = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2390 index, info->delta[i]);
6de9cd9a
DN
2391 }
2392
2393 /* Multiply by the stride. */
ecc54e6e
RS
2394 if (!integer_onep (stride))
2395 index = fold_build2 (MULT_EXPR, gfc_array_index_type, index, stride);
6de9cd9a
DN
2396
2397 return index;
2398}
2399
2400
2401/* Build a scalarized reference to an array. */
2402
2403static void
2404gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
2405{
2406 gfc_ss_info *info;
1d6b7f39 2407 tree decl = NULL_TREE;
6de9cd9a
DN
2408 tree index;
2409 tree tmp;
2410 int n;
2411
2412 info = &se->ss->data.info;
2413 if (ar)
2414 n = se->loop->order[0];
2415 else
2416 n = 0;
2417
2418 index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
2419 info->stride0);
2420 /* Add the offset for this dimension to the stored offset for all other
2421 dimensions. */
62511fb1
RS
2422 if (!integer_zerop (info->offset))
2423 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset);
6de9cd9a 2424
1d6b7f39
PT
2425 if (se->ss->expr && is_subref_array (se->ss->expr))
2426 decl = se->ss->expr->symtree->n.sym->backend_decl;
2427
38611275 2428 tmp = build_fold_indirect_ref (info->data);
1d6b7f39 2429 se->expr = gfc_build_array_ref (tmp, index, decl);
6de9cd9a
DN
2430}
2431
2432
2433/* Translate access of temporary array. */
2434
2435void
2436gfc_conv_tmp_array_ref (gfc_se * se)
2437{
40f20186 2438 se->string_length = se->ss->string_length;
6de9cd9a
DN
2439 gfc_conv_scalarized_array_ref (se, NULL);
2440}
2441
2442
2443/* Build an array reference. se->expr already holds the array descriptor.
2444 This should be either a variable, indirect variable reference or component
2445 reference. For arrays which do not have a descriptor, se->expr will be
2446 the data pointer.
2447 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
2448
2449void
dd18a33b
FXC
2450gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
2451 locus * where)
6de9cd9a
DN
2452{
2453 int n;
2454 tree index;
2455 tree tmp;
2456 tree stride;
6de9cd9a 2457 gfc_se indexse;
59e36b72 2458 gfc_se tmpse;
6de9cd9a 2459
e7dc5b4f 2460 /* Handle scalarized references separately. */
6de9cd9a
DN
2461 if (ar->type != AR_ELEMENT)
2462 {
2463 gfc_conv_scalarized_array_ref (se, ar);
068e7338 2464 gfc_advance_se_ss_chain (se);
6de9cd9a
DN
2465 return;
2466 }
2467
7ab92584 2468 index = gfc_index_zero_node;
6de9cd9a 2469
6de9cd9a
DN
2470 /* Calculate the offsets from all the dimensions. */
2471 for (n = 0; n < ar->dimen; n++)
2472 {
1f2959f0 2473 /* Calculate the index for this dimension. */
068e7338 2474 gfc_init_se (&indexse, se);
6de9cd9a
DN
2475 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
2476 gfc_add_block_to_block (&se->pre, &indexse.pre);
2477
d3d3011f 2478 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
6de9cd9a
DN
2479 {
2480 /* Check array bounds. */
2481 tree cond;
dd18a33b 2482 char *msg;
6de9cd9a 2483
a90552d5
FXC
2484 /* Evaluate the indexse.expr only once. */
2485 indexse.expr = save_expr (indexse.expr);
2486
c099916d 2487 /* Lower bound. */
6de9cd9a 2488 tmp = gfc_conv_array_lbound (se->expr, n);
59e36b72
PT
2489 if (sym->attr.temporary)
2490 {
2491 gfc_init_se (&tmpse, se);
2492 gfc_conv_expr_type (&tmpse, ar->as->lower[n],
2493 gfc_array_index_type);
2494 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2495 tmp = tmpse.expr;
2496 }
2497
10c7a96f
SB
2498 cond = fold_build2 (LT_EXPR, boolean_type_node,
2499 indexse.expr, tmp);
dd18a33b 2500 asprintf (&msg, "%s for array '%s', "
1954a27b
TB
2501 "lower bound of dimension %d exceeded (%%ld < %%ld)",
2502 gfc_msg_fault, sym->name, n+1);
0d52899f 2503 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
c8fe94c7
FXC
2504 fold_convert (long_integer_type_node,
2505 indexse.expr),
2506 fold_convert (long_integer_type_node, tmp));
dd18a33b 2507 gfc_free (msg);
6de9cd9a 2508
c099916d
FXC
2509 /* Upper bound, but not for the last dimension of assumed-size
2510 arrays. */
2511 if (n < ar->dimen - 1
2512 || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
2513 {
2514 tmp = gfc_conv_array_ubound (se->expr, n);
59e36b72
PT
2515 if (sym->attr.temporary)
2516 {
2517 gfc_init_se (&tmpse, se);
2518 gfc_conv_expr_type (&tmpse, ar->as->upper[n],
2519 gfc_array_index_type);
2520 gfc_add_block_to_block (&se->pre, &tmpse.pre);
2521 tmp = tmpse.expr;
2522 }
2523
c099916d
FXC
2524 cond = fold_build2 (GT_EXPR, boolean_type_node,
2525 indexse.expr, tmp);
2526 asprintf (&msg, "%s for array '%s', "
1954a27b
TB
2527 "upper bound of dimension %d exceeded (%%ld > %%ld)",
2528 gfc_msg_fault, sym->name, n+1);
0d52899f 2529 gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
c8fe94c7
FXC
2530 fold_convert (long_integer_type_node,
2531 indexse.expr),
2532 fold_convert (long_integer_type_node, tmp));
c099916d
FXC
2533 gfc_free (msg);
2534 }
6de9cd9a
DN
2535 }
2536
2537 /* Multiply the index by the stride. */
2538 stride = gfc_conv_array_stride (se->expr, n);
10c7a96f
SB
2539 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
2540 stride);
6de9cd9a
DN
2541
2542 /* And add it to the total. */
10c7a96f 2543 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
6de9cd9a
DN
2544 }
2545
6de9cd9a
DN
2546 tmp = gfc_conv_array_offset (se->expr);
2547 if (!integer_zerop (tmp))
10c7a96f 2548 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, index, tmp);
1d6b7f39 2549
6de9cd9a
DN
2550 /* Access the calculated element. */
2551 tmp = gfc_conv_array_data (se->expr);
38611275 2552 tmp = build_fold_indirect_ref (tmp);
1d6b7f39 2553 se->expr = gfc_build_array_ref (tmp, index, sym->backend_decl);
6de9cd9a
DN
2554}
2555
2556
2557/* Generate the code to be executed immediately before entering a
2558 scalarization loop. */
2559
2560static void
2561gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
2562 stmtblock_t * pblock)
2563{
2564 tree index;
2565 tree stride;
2566 gfc_ss_info *info;
2567 gfc_ss *ss;
2568 gfc_se se;
2569 int i;
2570
2571 /* This code will be executed before entering the scalarization loop
2572 for this dimension. */
2573 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2574 {
2575 if ((ss->useflags & flag) == 0)
2576 continue;
2577
2578 if (ss->type != GFC_SS_SECTION
e9cfef64
PB
2579 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2580 && ss->type != GFC_SS_COMPONENT)
6de9cd9a
DN
2581 continue;
2582
2583 info = &ss->data.info;
2584
2585 if (dim >= info->dimen)
2586 continue;
2587
2588 if (dim == info->dimen - 1)
2589 {
2590 /* For the outermost loop calculate the offset due to any
2591 elemental dimensions. It will have been initialized with the
2592 base offset of the array. */
2593 if (info->ref)
2594 {
2595 for (i = 0; i < info->ref->u.ar.dimen; i++)
2596 {
2597 if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
2598 continue;
2599
2600 gfc_init_se (&se, NULL);
2601 se.loop = loop;
2602 se.expr = info->descriptor;
2603 stride = gfc_conv_array_stride (info->descriptor, i);
2604 index = gfc_conv_array_index_offset (&se, info, i, -1,
2605 &info->ref->u.ar,
2606 stride);
2607 gfc_add_block_to_block (pblock, &se.pre);
2608
10c7a96f
SB
2609 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2610 info->offset, index);
6de9cd9a
DN
2611 info->offset = gfc_evaluate_now (info->offset, pblock);
2612 }
2613
2614 i = loop->order[0];
2615 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2616 }
2617 else
2618 stride = gfc_conv_array_stride (info->descriptor, 0);
2619
2620 /* Calculate the stride of the innermost loop. Hopefully this will
2621 allow the backend optimizers to do their stuff more effectively.
2622 */
2623 info->stride0 = gfc_evaluate_now (stride, pblock);
2624 }
2625 else
2626 {
2627 /* Add the offset for the previous loop dimension. */
2628 gfc_array_ref *ar;
2629
2630 if (info->ref)
2631 {
2632 ar = &info->ref->u.ar;
2633 i = loop->order[dim + 1];
2634 }
2635 else
2636 {
2637 ar = NULL;
2638 i = dim + 1;
2639 }
2640
2641 gfc_init_se (&se, NULL);
2642 se.loop = loop;
2643 se.expr = info->descriptor;
2644 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
2645 index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
2646 ar, stride);
2647 gfc_add_block_to_block (pblock, &se.pre);
10c7a96f
SB
2648 info->offset = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2649 info->offset, index);
6de9cd9a
DN
2650 info->offset = gfc_evaluate_now (info->offset, pblock);
2651 }
2652
e7dc5b4f 2653 /* Remember this offset for the second loop. */
6de9cd9a
DN
2654 if (dim == loop->temp_dim - 1)
2655 info->saved_offset = info->offset;
2656 }
2657}
2658
2659
2660/* Start a scalarized expression. Creates a scope and declares loop
2661 variables. */
2662
2663void
2664gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
2665{
2666 int dim;
2667 int n;
2668 int flags;
2669
6e45f57b 2670 gcc_assert (!loop->array_parameter);
6de9cd9a
DN
2671
2672 for (dim = loop->dimen - 1; dim >= 0; dim--)
2673 {
2674 n = loop->order[dim];
2675
2676 gfc_start_block (&loop->code[n]);
2677
2678 /* Create the loop variable. */
2679 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
2680
2681 if (dim < loop->temp_dim)
2682 flags = 3;
2683 else
2684 flags = 1;
2685 /* Calculate values that will be constant within this loop. */
2686 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
2687 }
2688 gfc_start_block (pbody);
2689}
2690
2691
2692/* Generates the actual loop code for a scalarization loop. */
2693
2694static void
2695gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
2696 stmtblock_t * pbody)
2697{
2698 stmtblock_t block;
2699 tree cond;
2700 tree tmp;
2701 tree loopbody;
2702 tree exit_label;
34d01e1d
VL
2703 tree stmt;
2704 tree init;
2705 tree incr;
6de9cd9a 2706
34d01e1d
VL
2707 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
2708 == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
2709 && n == loop->dimen - 1)
2710 {
2711 /* We create an OMP_FOR construct for the outermost scalarized loop. */
2712 init = make_tree_vec (1);
2713 cond = make_tree_vec (1);
2714 incr = make_tree_vec (1);
2715
2716 /* Cycle statement is implemented with a goto. Exit statement must not
2717 be present for this loop. */
2718 exit_label = gfc_build_label_decl (NULL_TREE);
2719 TREE_USED (exit_label) = 1;
2720
2721 /* Label for cycle statements (if needed). */
2722 tmp = build1_v (LABEL_EXPR, exit_label);
2723 gfc_add_expr_to_block (pbody, tmp);
2724
2725 stmt = make_node (OMP_FOR);
2726
2727 TREE_TYPE (stmt) = void_type_node;
2728 OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
2729
2730 OMP_FOR_CLAUSES (stmt) = build_omp_clause (OMP_CLAUSE_SCHEDULE);
2731 OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
2732 = OMP_CLAUSE_SCHEDULE_STATIC;
2733 if (ompws_flags & OMPWS_NOWAIT)
2734 OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
2735 = build_omp_clause (OMP_CLAUSE_NOWAIT);
2736
2737 /* Initialize the loopvar. */
2738 TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
2739 loop->from[n]);
2740 OMP_FOR_INIT (stmt) = init;
2741 /* The exit condition. */
2742 TREE_VEC_ELT (cond, 0) = build2 (LE_EXPR, boolean_type_node,
2743 loop->loopvar[n], loop->to[n]);
2744 OMP_FOR_COND (stmt) = cond;
2745 /* Increment the loopvar. */
2746 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
2747 loop->loopvar[n], gfc_index_one_node);
2748 TREE_VEC_ELT (incr, 0) = fold_build2 (MODIFY_EXPR,
2749 void_type_node, loop->loopvar[n], tmp);
2750 OMP_FOR_INCR (stmt) = incr;
2751
2752 ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
2753 gfc_add_expr_to_block (&loop->code[n], stmt);
2754 }
2755 else
2756 {
2757 loopbody = gfc_finish_block (pbody);
6de9cd9a 2758
34d01e1d
VL
2759 /* Initialize the loopvar. */
2760 gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
6de9cd9a 2761
34d01e1d 2762 exit_label = gfc_build_label_decl (NULL_TREE);
6de9cd9a 2763
34d01e1d
VL
2764 /* Generate the loop body. */
2765 gfc_init_block (&block);
6de9cd9a 2766
34d01e1d
VL
2767 /* The exit condition. */
2768 cond = fold_build2 (GT_EXPR, boolean_type_node,
2769 loop->loopvar[n], loop->to[n]);
2770 tmp = build1_v (GOTO_EXPR, exit_label);
2771 TREE_USED (exit_label) = 1;
2772 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
2773 gfc_add_expr_to_block (&block, tmp);
6de9cd9a 2774
34d01e1d
VL
2775 /* The main body. */
2776 gfc_add_expr_to_block (&block, loopbody);
6de9cd9a 2777
34d01e1d
VL
2778 /* Increment the loopvar. */
2779 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2780 loop->loopvar[n], gfc_index_one_node);
2781 gfc_add_modify (&block, loop->loopvar[n], tmp);
6de9cd9a 2782
34d01e1d
VL
2783 /* Build the loop. */
2784 tmp = gfc_finish_block (&block);
2785 tmp = build1_v (LOOP_EXPR, tmp);
2786 gfc_add_expr_to_block (&loop->code[n], tmp);
2787
2788 /* Add the exit label. */
2789 tmp = build1_v (LABEL_EXPR, exit_label);
2790 gfc_add_expr_to_block (&loop->code[n], tmp);
2791 }
6de9cd9a 2792
6de9cd9a
DN
2793}
2794
2795
2796/* Finishes and generates the loops for a scalarized expression. */
2797
2798void
2799gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
2800{
2801 int dim;
2802 int n;
2803 gfc_ss *ss;
2804 stmtblock_t *pblock;
2805 tree tmp;
2806
2807 pblock = body;
2808 /* Generate the loops. */
2809 for (dim = 0; dim < loop->dimen; dim++)
2810 {
2811 n = loop->order[dim];
2812 gfc_trans_scalarized_loop_end (loop, n, pblock);
2813 loop->loopvar[n] = NULL_TREE;
2814 pblock = &loop->code[n];
2815 }
2816
2817 tmp = gfc_finish_block (pblock);
2818 gfc_add_expr_to_block (&loop->pre, tmp);
2819
2820 /* Clear all the used flags. */
2821 for (ss = loop->ss; ss; ss = ss->loop_chain)
2822 ss->useflags = 0;
2823}
2824
2825
2826/* Finish the main body of a scalarized expression, and start the secondary
2827 copying body. */
2828
2829void
2830gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
2831{
2832 int dim;
2833 int n;
2834 stmtblock_t *pblock;
2835 gfc_ss *ss;
2836
2837 pblock = body;
2838 /* We finish as many loops as are used by the temporary. */
2839 for (dim = 0; dim < loop->temp_dim - 1; dim++)
2840 {
2841 n = loop->order[dim];
2842 gfc_trans_scalarized_loop_end (loop, n, pblock);
2843 loop->loopvar[n] = NULL_TREE;
2844 pblock = &loop->code[n];
2845 }
2846
2847 /* We don't want to finish the outermost loop entirely. */
2848 n = loop->order[loop->temp_dim - 1];
2849 gfc_trans_scalarized_loop_end (loop, n, pblock);
2850
2851 /* Restore the initial offsets. */
2852 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2853 {
2854 if ((ss->useflags & 2) == 0)
2855 continue;
2856
2857 if (ss->type != GFC_SS_SECTION
e9cfef64
PB
2858 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
2859 && ss->type != GFC_SS_COMPONENT)
6de9cd9a
DN
2860 continue;
2861
2862 ss->data.info.offset = ss->data.info.saved_offset;
2863 }
2864
2865 /* Restart all the inner loops we just finished. */
2866 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
2867 {
2868 n = loop->order[dim];
2869
2870 gfc_start_block (&loop->code[n]);
2871
2872 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
2873
2874 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
2875 }
2876
2877 /* Start a block for the secondary copying code. */
2878 gfc_start_block (body);
2879}
2880
2881
2882/* Calculate the upper bound of an array section. */
2883
2884static tree
2885gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
2886{
2887 int dim;
6de9cd9a
DN
2888 gfc_expr *end;
2889 tree desc;
2890 tree bound;
2891 gfc_se se;
7a70c12d 2892 gfc_ss_info *info;
6de9cd9a 2893
6e45f57b 2894 gcc_assert (ss->type == GFC_SS_SECTION);
6de9cd9a 2895
7a70c12d
RS
2896 info = &ss->data.info;
2897 dim = info->dim[n];
6de9cd9a 2898
7a70c12d
RS
2899 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2900 /* We'll calculate the upper bound once we have access to the
2901 vector's descriptor. */
2902 return NULL;
2903
2904 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2905 desc = info->descriptor;
2906 end = info->ref->u.ar.end[dim];
6de9cd9a
DN
2907
2908 if (end)
2909 {
2910 /* The upper bound was specified. */
2911 gfc_init_se (&se, NULL);
2912 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2913 gfc_add_block_to_block (pblock, &se.pre);
2914 bound = se.expr;
2915 }
2916 else
2917 {
f7b529fa 2918 /* No upper bound was specified, so use the bound of the array. */
6de9cd9a
DN
2919 bound = gfc_conv_array_ubound (desc, dim);
2920 }
2921
2922 return bound;
2923}
2924
2925
2926/* Calculate the lower bound of an array section. */
2927
2928static void
2929gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
2930{
2931 gfc_expr *start;
8424e0d8 2932 gfc_expr *end;
6de9cd9a 2933 gfc_expr *stride;
6de9cd9a
DN
2934 tree desc;
2935 gfc_se se;
2936 gfc_ss_info *info;
2937 int dim;
2938
7a70c12d 2939 gcc_assert (ss->type == GFC_SS_SECTION);
6de9cd9a 2940
7a70c12d 2941 info = &ss->data.info;
6de9cd9a
DN
2942 dim = info->dim[n];
2943
7a70c12d 2944 if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
6de9cd9a 2945 {
7a70c12d
RS
2946 /* We use a zero-based index to access the vector. */
2947 info->start[n] = gfc_index_zero_node;
8424e0d8 2948 info->end[n] = gfc_index_zero_node;
7a70c12d
RS
2949 info->stride[n] = gfc_index_one_node;
2950 return;
6de9cd9a
DN
2951 }
2952
7a70c12d
RS
2953 gcc_assert (info->ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
2954 desc = info->descriptor;
2955 start = info->ref->u.ar.start[dim];
8424e0d8 2956 end = info->ref->u.ar.end[dim];
7a70c12d 2957 stride = info->ref->u.ar.stride[dim];
6de9cd9a
DN
2958
2959 /* Calculate the start of the range. For vector subscripts this will
2960 be the range of the vector. */
2961 if (start)
2962 {
2963 /* Specified section start. */
2964 gfc_init_se (&se, NULL);
2965 gfc_conv_expr_type (&se, start, gfc_array_index_type);
2966 gfc_add_block_to_block (&loop->pre, &se.pre);
2967 info->start[n] = se.expr;
2968 }
2969 else
2970 {
2971 /* No lower bound specified so use the bound of the array. */
2972 info->start[n] = gfc_conv_array_lbound (desc, dim);
2973 }
2974 info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
2975
8424e0d8
PT
2976 /* Similarly calculate the end. Although this is not used in the
2977 scalarizer, it is needed when checking bounds and where the end
2978 is an expression with side-effects. */
2979 if (end)
2980 {
2981 /* Specified section start. */
2982 gfc_init_se (&se, NULL);
2983 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2984 gfc_add_block_to_block (&loop->pre, &se.pre);
2985 info->end[n] = se.expr;
2986 }
2987 else
2988 {
2989 /* No upper bound specified so use the bound of the array. */
2990 info->end[n] = gfc_conv_array_ubound (desc, dim);
2991 }
2992 info->end[n] = gfc_evaluate_now (info->end[n], &loop->pre);
2993
6de9cd9a
DN
2994 /* Calculate the stride. */
2995 if (stride == NULL)
7ab92584 2996 info->stride[n] = gfc_index_one_node;
6de9cd9a
DN
2997 else
2998 {
2999 gfc_init_se (&se, NULL);
3000 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
3001 gfc_add_block_to_block (&loop->pre, &se.pre);
3002 info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
3003 }
3004}
3005
3006
3007/* Calculates the range start and stride for a SS chain. Also gets the
3008 descriptor and data pointer. The range of vector subscripts is the size
3009 of the vector. Array bounds are also checked. */
3010
3011void
3012gfc_conv_ss_startstride (gfc_loopinfo * loop)
3013{
3014 int n;
3015 tree tmp;
3016 gfc_ss *ss;
6de9cd9a
DN
3017 tree desc;
3018
3019 loop->dimen = 0;
3020 /* Determine the rank of the loop. */
3021 for (ss = loop->ss;
3022 ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
3023 {
3024 switch (ss->type)
3025 {
3026 case GFC_SS_SECTION:
3027 case GFC_SS_CONSTRUCTOR:
3028 case GFC_SS_FUNCTION:
e9cfef64 3029 case GFC_SS_COMPONENT:
6de9cd9a
DN
3030 loop->dimen = ss->data.info.dimen;
3031 break;
3032
f5f701ad
PT
3033 /* As usual, lbound and ubound are exceptions!. */
3034 case GFC_SS_INTRINSIC:
cd5ecab6 3035 switch (ss->expr->value.function.isym->id)
f5f701ad
PT
3036 {
3037 case GFC_ISYM_LBOUND:
3038 case GFC_ISYM_UBOUND:
3039 loop->dimen = ss->data.info.dimen;
3040
3041 default:
3042 break;
3043 }
3044
6de9cd9a
DN
3045 default:
3046 break;
3047 }
3048 }
3049
ca39e6f2
FXC
3050 /* We should have determined the rank of the expression by now. If
3051 not, that's bad news. */
3052 gcc_assert (loop->dimen != 0);
6de9cd9a 3053
13413760 3054 /* Loop over all the SS in the chain. */
6de9cd9a
DN
3055 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3056 {
e9cfef64
PB
3057 if (ss->expr && ss->expr->shape && !ss->shape)
3058 ss->shape = ss->expr->shape;
3059
6de9cd9a
DN
3060 switch (ss->type)
3061 {
3062 case GFC_SS_SECTION:
3063 /* Get the descriptor for the array. */
3064 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
3065
3066 for (n = 0; n < ss->data.info.dimen; n++)
3067 gfc_conv_section_startstride (loop, ss, n);
3068 break;
3069
f5f701ad 3070 case GFC_SS_INTRINSIC:
cd5ecab6 3071 switch (ss->expr->value.function.isym->id)
f5f701ad
PT
3072 {
3073 /* Fall through to supply start and stride. */
3074 case GFC_ISYM_LBOUND:
3075 case GFC_ISYM_UBOUND:
3076 break;
3077 default:
3078 continue;
3079 }
3080
6de9cd9a
DN
3081 case GFC_SS_CONSTRUCTOR:
3082 case GFC_SS_FUNCTION:
3083 for (n = 0; n < ss->data.info.dimen; n++)
3084 {
7ab92584 3085 ss->data.info.start[n] = gfc_index_zero_node;
8424e0d8 3086 ss->data.info.end[n] = gfc_index_zero_node;
7ab92584 3087 ss->data.info.stride[n] = gfc_index_one_node;
6de9cd9a
DN
3088 }
3089 break;
3090
3091 default:
3092 break;
3093 }
3094 }
3095
3096 /* The rest is just runtime bound checking. */
d3d3011f 3097 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
6de9cd9a
DN
3098 {
3099 stmtblock_t block;
ef31fe62 3100 tree lbound, ubound;
6de9cd9a
DN
3101 tree end;
3102 tree size[GFC_MAX_DIMENSIONS];
ef31fe62 3103 tree stride_pos, stride_neg, non_zerosized, tmp2;
6de9cd9a 3104 gfc_ss_info *info;
dd18a33b 3105 char *msg;
6de9cd9a
DN
3106 int dim;
3107
3108 gfc_start_block (&block);
3109
6de9cd9a
DN
3110 for (n = 0; n < loop->dimen; n++)
3111 size[n] = NULL_TREE;
3112
3113 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3114 {
ba4698e1
FXC
3115 stmtblock_t inner;
3116
6de9cd9a
DN
3117 if (ss->type != GFC_SS_SECTION)
3118 continue;
3119
ba4698e1
FXC
3120 gfc_start_block (&inner);
3121
6de9cd9a
DN
3122 /* TODO: range checking for mapped dimensions. */
3123 info = &ss->data.info;
3124
7a70c12d
RS
3125 /* This code only checks ranges. Elemental and vector
3126 dimensions are checked later. */
6de9cd9a
DN
3127 for (n = 0; n < loop->dimen; n++)
3128 {
c099916d
FXC
3129 bool check_upper;
3130
6de9cd9a 3131 dim = info->dim[n];
7a70c12d
RS
3132 if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
3133 continue;
c099916d 3134
1954a27b 3135 if (dim == info->ref->u.ar.dimen - 1
ef31fe62
FXC
3136 && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
3137 || info->ref->u.ar.as->cp_was_assumed))
c099916d
FXC
3138 check_upper = false;
3139 else
3140 check_upper = true;
ef31fe62
FXC
3141
3142 /* Zero stride is not allowed. */
3143 tmp = fold_build2 (EQ_EXPR, boolean_type_node, info->stride[n],
3144 gfc_index_zero_node);
3145 asprintf (&msg, "Zero stride is not allowed, for dimension %d "
3146 "of array '%s'", info->dim[n]+1,
3147 ss->expr->symtree->name);
0d52899f
TB
3148 gfc_trans_runtime_check (true, false, tmp, &inner,
3149 &ss->expr->where, msg);
ef31fe62
FXC
3150 gfc_free (msg);
3151
c099916d
FXC
3152 desc = ss->data.info.descriptor;
3153
3154 /* This is the run-time equivalent of resolve.c's
3155 check_dimension(). The logical is more readable there
3156 than it is here, with all the trees. */
3157 lbound = gfc_conv_array_lbound (desc, dim);
3158 end = info->end[n];
3159 if (check_upper)
3160 ubound = gfc_conv_array_ubound (desc, dim);
3161 else
3162 ubound = NULL;
3163
ef31fe62
FXC
3164 /* non_zerosized is true when the selected range is not
3165 empty. */
3166 stride_pos = fold_build2 (GT_EXPR, boolean_type_node,
3167 info->stride[n], gfc_index_zero_node);
3168 tmp = fold_build2 (LE_EXPR, boolean_type_node, info->start[n],
3169 end);
3170 stride_pos = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3171 stride_pos, tmp);
3172
3173 stride_neg = fold_build2 (LT_EXPR, boolean_type_node,
3174 info->stride[n], gfc_index_zero_node);
3175 tmp = fold_build2 (GE_EXPR, boolean_type_node, info->start[n],
3176 end);
3177 stride_neg = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3178 stride_neg, tmp);
3179 non_zerosized = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
3180 stride_pos, stride_neg);
3181
3182 /* Check the start of the range against the lower and upper
3183 bounds of the array, if the range is not empty. */
3184 tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
3185 lbound);
3186 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3187 non_zerosized, tmp);
dd18a33b 3188 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
1954a27b 3189 " exceeded (%%ld < %%ld)", gfc_msg_fault,
c8fe94c7 3190 info->dim[n]+1, ss->expr->symtree->name);
0d52899f
TB
3191 gfc_trans_runtime_check (true, false, tmp, &inner,
3192 &ss->expr->where, msg,
c8fe94c7
FXC
3193 fold_convert (long_integer_type_node,
3194 info->start[n]),
3195 fold_convert (long_integer_type_node,
3196 lbound));
dd18a33b 3197 gfc_free (msg);
6de9cd9a 3198
c099916d
FXC
3199 if (check_upper)
3200 {
3201 tmp = fold_build2 (GT_EXPR, boolean_type_node,
3202 info->start[n], ubound);
3203 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3204 non_zerosized, tmp);
3205 asprintf (&msg, "%s, upper bound of dimension %d of array "
1954a27b
TB
3206 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3207 info->dim[n]+1, ss->expr->symtree->name);
0d52899f
TB
3208 gfc_trans_runtime_check (true, false, tmp, &inner,
3209 &ss->expr->where, msg,
c8fe94c7
FXC
3210 fold_convert (long_integer_type_node, info->start[n]),
3211 fold_convert (long_integer_type_node, ubound));
c099916d
FXC
3212 gfc_free (msg);
3213 }
ef31fe62
FXC
3214
3215 /* Compute the last element of the range, which is not
3216 necessarily "end" (think 0:5:3, which doesn't contain 5)
3217 and check it against both lower and upper bounds. */
3218 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3219 info->start[n]);
3220 tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
3221 info->stride[n]);
3222 tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3223 tmp2);
3224
3225 tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
3226 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3227 non_zerosized, tmp);
3228 asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
1954a27b 3229 " exceeded (%%ld < %%ld)", gfc_msg_fault,
c8fe94c7 3230 info->dim[n]+1, ss->expr->symtree->name);
0d52899f
TB
3231 gfc_trans_runtime_check (true, false, tmp, &inner,
3232 &ss->expr->where, msg,
c8fe94c7
FXC
3233 fold_convert (long_integer_type_node,
3234 tmp2),
3235 fold_convert (long_integer_type_node,
3236 lbound));
ef31fe62
FXC
3237 gfc_free (msg);
3238
c099916d
FXC
3239 if (check_upper)
3240 {
3241 tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
3242 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
3243 non_zerosized, tmp);
3244 asprintf (&msg, "%s, upper bound of dimension %d of array "
1954a27b
TB
3245 "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
3246 info->dim[n]+1, ss->expr->symtree->name);
0d52899f
TB
3247 gfc_trans_runtime_check (true, false, tmp, &inner,
3248 &ss->expr->where, msg,
c8fe94c7
FXC
3249 fold_convert (long_integer_type_node, tmp2),
3250 fold_convert (long_integer_type_node, ubound));
c099916d
FXC
3251 gfc_free (msg);
3252 }
6de9cd9a
DN
3253
3254 /* Check the section sizes match. */
10c7a96f
SB
3255 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
3256 info->start[n]);
3257 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
3258 info->stride[n]);
7ac61957
JD
3259 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3260 gfc_index_one_node, tmp);
4c7382bb
FXC
3261 tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
3262 build_int_cst (gfc_array_index_type, 0));
6de9cd9a
DN
3263 /* We remember the size of the first section, and check all the
3264 others against this. */
3265 if (size[n])
3266 {
a50ba82d
FXC
3267 tree tmp3;
3268
3269 tmp3 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
dd18a33b 3270 asprintf (&msg, "%s, size mismatch for dimension %d "
c8fe94c7
FXC
3271 "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
3272 info->dim[n]+1, ss->expr->symtree->name);
0d52899f
TB
3273 gfc_trans_runtime_check (true, false, tmp3, &inner,
3274 &ss->expr->where, msg,
c8fe94c7
FXC
3275 fold_convert (long_integer_type_node, tmp),
3276 fold_convert (long_integer_type_node, size[n]));
dd18a33b 3277 gfc_free (msg);
6de9cd9a
DN
3278 }
3279 else
ba4698e1 3280 size[n] = gfc_evaluate_now (tmp, &inner);
6de9cd9a 3281 }
ba4698e1
FXC
3282
3283 tmp = gfc_finish_block (&inner);
3284
3285 /* For optional arguments, only check bounds if the argument is
3286 present. */
3287 if (ss->expr->symtree->n.sym->attr.optional
3288 || ss->expr->symtree->n.sym->attr.not_always_present)
3289 tmp = build3_v (COND_EXPR,
3290 gfc_conv_expr_present (ss->expr->symtree->n.sym),
3291 tmp, build_empty_stmt ());
3292
3293 gfc_add_expr_to_block (&block, tmp);
3294
6de9cd9a 3295 }
6de9cd9a
DN
3296
3297 tmp = gfc_finish_block (&block);
3298 gfc_add_expr_to_block (&loop->pre, tmp);
3299 }
3300}
3301
3302
13795658 3303/* Return true if the two SS could be aliased, i.e. both point to the same data
6de9cd9a
DN
3304 object. */
3305/* TODO: resolve aliases based on frontend expressions. */
3306
3307static int
3308gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
3309{
3310 gfc_ref *lref;
3311 gfc_ref *rref;
3312 gfc_symbol *lsym;
3313 gfc_symbol *rsym;
3314
3315 lsym = lss->expr->symtree->n.sym;
3316 rsym = rss->expr->symtree->n.sym;
3317 if (gfc_symbols_could_alias (lsym, rsym))
3318 return 1;
3319
3320 if (rsym->ts.type != BT_DERIVED
3321 && lsym->ts.type != BT_DERIVED)
3322 return 0;
3323
13413760 3324 /* For derived types we must check all the component types. We can ignore
6de9cd9a
DN
3325 array references as these will have the same base type as the previous
3326 component ref. */
3327 for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
3328 {
3329 if (lref->type != REF_COMPONENT)
3330 continue;
3331
3332 if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
3333 return 1;
3334
3335 for (rref = rss->expr->ref; rref != rss->data.info.ref;
3336 rref = rref->next)
3337 {
3338 if (rref->type != REF_COMPONENT)
3339 continue;
3340
3341 if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
3342 return 1;
3343 }
3344 }
3345
3346 for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
3347 {
3348 if (rref->type != REF_COMPONENT)
3349 break;
3350
3351 if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
3352 return 1;
3353 }
3354
3355 return 0;
3356}
3357
3358
3359/* Resolve array data dependencies. Creates a temporary if required. */
3360/* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
3361 dependency.c. */
3362
3363void
3364gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
3365 gfc_ss * rss)
3366{
3367 gfc_ss *ss;
3368 gfc_ref *lref;
3369 gfc_ref *rref;
3370 gfc_ref *aref;
3371 int nDepend = 0;
3372 int temp_dim = 0;
3373
3374 loop->temp_ss = NULL;
3375 aref = dest->data.info.ref;
3376 temp_dim = 0;
3377
3378 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
3379 {
3380 if (ss->type != GFC_SS_SECTION)
3381 continue;
3382
7d1f1e61 3383 if (dest->expr->symtree->n.sym != ss->expr->symtree->n.sym)
6de9cd9a 3384 {
7d1f1e61
PT
3385 if (gfc_could_be_alias (dest, ss)
3386 || gfc_are_equivalenced_arrays (dest->expr, ss->expr))
3387 {
3388 nDepend = 1;
3389 break;
3390 }
6de9cd9a 3391 }
7d1f1e61 3392 else
6de9cd9a
DN
3393 {
3394 lref = dest->expr->ref;
3395 rref = ss->expr->ref;
3396
3397 nDepend = gfc_dep_resolver (lref, rref);
4f06d65b
PT
3398 if (nDepend == 1)
3399 break;
6de9cd9a
DN
3400#if 0
3401 /* TODO : loop shifting. */
3402 if (nDepend == 1)
3403 {
3404 /* Mark the dimensions for LOOP SHIFTING */
3405 for (n = 0; n < loop->dimen; n++)
3406 {
3407 int dim = dest->data.info.dim[n];
3408
3409 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
3410 depends[n] = 2;
3411 else if (! gfc_is_same_range (&lref->u.ar,
3412 &rref->u.ar, dim, 0))
3413 depends[n] = 1;
3414 }
3415
13413760 3416 /* Put all the dimensions with dependencies in the
6de9cd9a
DN
3417 innermost loops. */
3418 dim = 0;
3419 for (n = 0; n < loop->dimen; n++)
3420 {
6e45f57b 3421 gcc_assert (loop->order[n] == n);
6de9cd9a
DN
3422 if (depends[n])
3423 loop->order[dim++] = n;
3424 }
3425 temp_dim = dim;
3426 for (n = 0; n < loop->dimen; n++)
3427 {
3428 if (! depends[n])
3429 loop->order[dim++] = n;
3430 }
3431
6e45f57b 3432 gcc_assert (dim == loop->dimen);
6de9cd9a
DN
3433 break;
3434 }
3435#endif
3436 }
3437 }
3438
3439 if (nDepend == 1)
3440 {
eca18fb4
AP
3441 tree base_type = gfc_typenode_for_spec (&dest->expr->ts);
3442 if (GFC_ARRAY_TYPE_P (base_type)
3443 || GFC_DESCRIPTOR_TYPE_P (base_type))
3444 base_type = gfc_get_element_type (base_type);
6de9cd9a
DN
3445 loop->temp_ss = gfc_get_ss ();
3446 loop->temp_ss->type = GFC_SS_TEMP;
eca18fb4 3447 loop->temp_ss->data.temp.type = base_type;
72caba17 3448 loop->temp_ss->string_length = dest->string_length;
6de9cd9a
DN
3449 loop->temp_ss->data.temp.dimen = loop->dimen;
3450 loop->temp_ss->next = gfc_ss_terminator;
3451 gfc_add_ss_to_loop (loop, loop->temp_ss);
3452 }
3453 else
3454 loop->temp_ss = NULL;
3455}
3456
3457
1f2959f0 3458/* Initialize the scalarization loop. Creates the loop variables. Determines
6de9cd9a
DN
3459 the range of the loop variables. Creates a temporary if required.
3460 Calculates how to transform from loop variables to array indices for each
3461 expression. Also generates code for scalar expressions which have been
f7b529fa 3462 moved outside the loop. */
6de9cd9a
DN
3463
3464void
bdfd2ff0 3465gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
6de9cd9a
DN
3466{
3467 int n;
3468 int dim;
3469 gfc_ss_info *info;
3470 gfc_ss_info *specinfo;
3471 gfc_ss *ss;
3472 tree tmp;
3473 tree len;
3474 gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
ec25720b
RS
3475 bool dynamic[GFC_MAX_DIMENSIONS];
3476 gfc_constructor *c;
6de9cd9a
DN
3477 mpz_t *cshape;
3478 mpz_t i;
3479
3480 mpz_init (i);
3481 for (n = 0; n < loop->dimen; n++)
3482 {
3483 loopspec[n] = NULL;
ec25720b 3484 dynamic[n] = false;
6de9cd9a
DN
3485 /* We use one SS term, and use that to determine the bounds of the
3486 loop for this dimension. We try to pick the simplest term. */
3487 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3488 {
e9cfef64 3489 if (ss->shape)
6de9cd9a
DN
3490 {
3491 /* The frontend has worked out the size for us. */
45bc572c
MM
3492 if (!loopspec[n] || !loopspec[n]->shape
3493 || !integer_zerop (loopspec[n]->data.info.start[n]))
3494 /* Prefer zero-based descriptors if possible. */
3495 loopspec[n] = ss;
6de9cd9a
DN
3496 continue;
3497 }
3498
3499 if (ss->type == GFC_SS_CONSTRUCTOR)
3500 {
e9cfef64 3501 /* An unknown size constructor will always be rank one.
40f20186 3502 Higher rank constructors will either have known shape,
e9cfef64 3503 or still be wrapped in a call to reshape. */
6e45f57b 3504 gcc_assert (loop->dimen == 1);
ec25720b
RS
3505
3506 /* Always prefer to use the constructor bounds if the size
3507 can be determined at compile time. Prefer not to otherwise,
3508 since the general case involves realloc, and it's better to
3509 avoid that overhead if possible. */
3510 c = ss->expr->value.constructor;
3511 dynamic[n] = gfc_get_array_constructor_size (&i, c);
3512 if (!dynamic[n] || !loopspec[n])
3513 loopspec[n] = ss;
6de9cd9a
DN
3514 continue;
3515 }
3516
fc90a8f2 3517 /* TODO: Pick the best bound if we have a choice between a
e9cfef64 3518 function and something else. */
fc90a8f2
PB
3519 if (ss->type == GFC_SS_FUNCTION)
3520 {
3521 loopspec[n] = ss;
3522 continue;
3523 }
3524
6de9cd9a
DN
3525 if (ss->type != GFC_SS_SECTION)
3526 continue;
3527
6de9cd9a
DN
3528 if (loopspec[n])
3529 specinfo = &loopspec[n]->data.info;
3530 else
3531 specinfo = NULL;
3532 info = &ss->data.info;
3533
ec25720b
RS
3534 if (!specinfo)
3535 loopspec[n] = ss;
6de9cd9a 3536 /* Criteria for choosing a loop specifier (most important first):
ec25720b 3537 doesn't need realloc
6de9cd9a
DN
3538 stride of one
3539 known stride
3540 known lower bound
3541 known upper bound
3542 */
ec25720b 3543 else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
6de9cd9a 3544 loopspec[n] = ss;
ec25720b
RS
3545 else if (integer_onep (info->stride[n])
3546 && !integer_onep (specinfo->stride[n]))
3547 loopspec[n] = ss;
3548 else if (INTEGER_CST_P (info->stride[n])
3549 && !INTEGER_CST_P (specinfo->stride[n]))
3550 loopspec[n] = ss;
3551 else if (INTEGER_CST_P (info->start[n])
3552 && !INTEGER_CST_P (specinfo->start[n]))
3553 loopspec[n] = ss;
3554 /* We don't work out the upper bound.
3555 else if (INTEGER_CST_P (info->finish[n])
3556 && ! INTEGER_CST_P (specinfo->finish[n]))
3557 loopspec[n] = ss; */
6de9cd9a
DN
3558 }
3559
ca39e6f2
FXC
3560 /* We should have found the scalarization loop specifier. If not,
3561 that's bad news. */
3562 gcc_assert (loopspec[n]);
6de9cd9a
DN
3563
3564 info = &loopspec[n]->data.info;
3565
3566 /* Set the extents of this range. */
e9cfef64 3567 cshape = loopspec[n]->shape;
6de9cd9a
DN
3568 if (cshape && INTEGER_CST_P (info->start[n])
3569 && INTEGER_CST_P (info->stride[n]))
3570 {
3571 loop->from[n] = info->start[n];
3572 mpz_set (i, cshape[n]);
3573 mpz_sub_ui (i, i, 1);
3574 /* To = from + (size - 1) * stride. */
3575 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
3576 if (!integer_onep (info->stride[n]))
10c7a96f
SB
3577 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3578 tmp, info->stride[n]);
3579 loop->to[n] = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3580 loop->from[n], tmp);
6de9cd9a
DN
3581 }
3582 else
3583 {
3584 loop->from[n] = info->start[n];
3585 switch (loopspec[n]->type)
3586 {
3587 case GFC_SS_CONSTRUCTOR:
ec25720b
RS
3588 /* The upper bound is calculated when we expand the
3589 constructor. */
3590 gcc_assert (loop->to[n] == NULL_TREE);
6de9cd9a
DN
3591 break;
3592
3593 case GFC_SS_SECTION:
993ac38b
PT
3594 /* Use the end expression if it exists and is not constant,
3595 so that it is only evaluated once. */
3596 if (info->end[n] && !INTEGER_CST_P (info->end[n]))
3597 loop->to[n] = info->end[n];
3598 else
3599 loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
3600 &loop->pre);
6de9cd9a
DN
3601 break;
3602
fc90a8f2
PB
3603 case GFC_SS_FUNCTION:
3604 /* The loop bound will be set when we generate the call. */
6e45f57b 3605 gcc_assert (loop->to[n] == NULL_TREE);
fc90a8f2
PB
3606 break;
3607
6de9cd9a 3608 default:
6e45f57b 3609 gcc_unreachable ();
6de9cd9a
DN
3610 }
3611 }
3612
3613 /* Transform everything so we have a simple incrementing variable. */
3614 if (integer_onep (info->stride[n]))
7ab92584 3615 info->delta[n] = gfc_index_zero_node;
6de9cd9a
DN
3616 else
3617 {
3618 /* Set the delta for this section. */
3619 info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
3620 /* Number of iterations is (end - start + step) / step.
3621 with start = 0, this simplifies to
3622 last = end / step;
3623 for (i = 0; i<=last; i++){...}; */
10c7a96f
SB
3624 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3625 loop->to[n], loop->from[n]);
4c7382bb 3626 tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type,
10c7a96f 3627 tmp, info->stride[n]);
4c7382bb
FXC
3628 tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
3629 build_int_cst (gfc_array_index_type, -1));
6de9cd9a
DN
3630 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
3631 /* Make the loop variable start at 0. */
7ab92584 3632 loop->from[n] = gfc_index_zero_node;
6de9cd9a
DN
3633 }
3634 }
3635
fc90a8f2
PB
3636 /* Add all the scalar code that can be taken out of the loops.
3637 This may include calculating the loop bounds, so do it before
3638 allocating the temporary. */
bdfd2ff0 3639 gfc_add_loop_ss_code (loop, loop->ss, false, where);
fc90a8f2 3640
6de9cd9a
DN
3641 /* If we want a temporary then create it. */
3642 if (loop->temp_ss != NULL)
3643 {
6e45f57b 3644 gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
640670c7
PT
3645
3646 /* Make absolutely sure that this is a complete type. */
3647 if (loop->temp_ss->string_length)
3648 loop->temp_ss->data.temp.type
d393bbd7
FXC
3649 = gfc_get_character_type_len_for_eltype
3650 (TREE_TYPE (loop->temp_ss->data.temp.type),
3651 loop->temp_ss->string_length);
640670c7 3652
6de9cd9a 3653 tmp = loop->temp_ss->data.temp.type;
40f20186 3654 len = loop->temp_ss->string_length;
6de9cd9a
DN
3655 n = loop->temp_ss->data.temp.dimen;
3656 memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
3657 loop->temp_ss->type = GFC_SS_SECTION;
3658 loop->temp_ss->data.info.dimen = n;
8e119f1b 3659 gfc_trans_create_temp_array (&loop->pre, &loop->post, loop,
12f681a0
DK
3660 &loop->temp_ss->data.info, tmp, NULL_TREE,
3661 false, true, false, where);
6de9cd9a
DN
3662 }
3663
6de9cd9a
DN
3664 for (n = 0; n < loop->temp_dim; n++)
3665 loopspec[loop->order[n]] = NULL;
3666
3667 mpz_clear (i);
3668
3669 /* For array parameters we don't have loop variables, so don't calculate the
3670 translations. */
3671 if (loop->array_parameter)
3672 return;
3673
3674 /* Calculate the translation from loop variables to array indices. */
3675 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
3676 {
45bc572c
MM
3677 if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT
3678 && ss->type != GFC_SS_CONSTRUCTOR)
3679
6de9cd9a
DN
3680 continue;
3681
3682 info = &ss->data.info;
3683
3684 for (n = 0; n < info->dimen; n++)
3685 {
3686 dim = info->dim[n];
3687
e9cfef64 3688 /* If we are specifying the range the delta is already set. */
6de9cd9a
DN
3689 if (loopspec[n] != ss)
3690 {
3691 /* Calculate the offset relative to the loop variable.
3692 First multiply by the stride. */
c96111c0
RS
3693 tmp = loop->from[n];
3694 if (!integer_onep (info->stride[n]))
3695 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
3696 tmp, info->stride[n]);
6de9cd9a
DN
3697
3698 /* Then subtract this from our starting value. */
10c7a96f
SB
3699 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3700 info->start[n], tmp);
6de9cd9a
DN
3701
3702 info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
3703 }
3704 }
3705 }
3706}
3707
3708
3709/* Fills in an array descriptor, and returns the size of the array. The size
3710 will be a simple_val, ie a variable or a constant. Also calculates the
1f2959f0 3711 offset of the base. Returns the size of the array.
6de9cd9a
DN
3712 {
3713 stride = 1;
3714 offset = 0;
3715 for (n = 0; n < rank; n++)
3716 {
3717 a.lbound[n] = specified_lower_bound;
3718 offset = offset + a.lbond[n] * stride;
3719 size = 1 - lbound;
3720 a.ubound[n] = specified_upper_bound;
3721 a.stride[n] = stride;
067feae3 3722 size = siz >= 0 ? ubound + size : 0; //size = ubound + 1 - lbound
6de9cd9a
DN
3723 stride = stride * size;
3724 }
3725 return (stride);
3726 } */
3727/*GCC ARRAYS*/
3728
3729static tree
3730gfc_array_init_size (tree descriptor, int rank, tree * poffset,
3731 gfc_expr ** lower, gfc_expr ** upper,
3732 stmtblock_t * pblock)
3733{
3734 tree type;
3735 tree tmp;
3736 tree size;
3737 tree offset;
3738 tree stride;
3c86fb4e
TK
3739 tree cond;
3740 tree or_expr;
3741 tree thencase;
3742 tree elsecase;
3743 tree var;
3744 stmtblock_t thenblock;
3745 stmtblock_t elseblock;
6de9cd9a
DN
3746 gfc_expr *ubound;
3747 gfc_se se;
3748 int n;
3749
3750 type = TREE_TYPE (descriptor);
3751
7ab92584
SB
3752 stride = gfc_index_one_node;
3753 offset = gfc_index_zero_node;
6de9cd9a
DN
3754
3755 /* Set the dtype. */
3756 tmp = gfc_conv_descriptor_dtype (descriptor);
726a989a 3757 gfc_add_modify (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
6de9cd9a 3758
3c86fb4e
TK
3759 or_expr = NULL_TREE;
3760
6de9cd9a
DN
3761 for (n = 0; n < rank; n++)
3762 {
3763 /* We have 3 possibilities for determining the size of the array:
3764 lower == NULL => lbound = 1, ubound = upper[n]
3765 upper[n] = NULL => lbound = 1, ubound = lower[n]
3766 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
3767 ubound = upper[n];
3768
3769 /* Set lower bound. */
3770 gfc_init_se (&se, NULL);
3771 if (lower == NULL)
7ab92584 3772 se.expr = gfc_index_one_node;
6de9cd9a
DN
3773 else
3774 {
6e45f57b 3775 gcc_assert (lower[n]);
6de9cd9a
DN
3776 if (ubound)
3777 {
3778 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
3779 gfc_add_block_to_block (pblock, &se.pre);
3780 }
3781 else
3782 {
7ab92584 3783 se.expr = gfc_index_one_node;
6de9cd9a
DN
3784 ubound = lower[n];
3785 }
3786 }
3787 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
726a989a 3788 gfc_add_modify (pblock, tmp, se.expr);
6de9cd9a
DN
3789
3790 /* Work out the offset for this component. */
10c7a96f
SB
3791 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
3792 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
6de9cd9a
DN
3793
3794 /* Start the calculation for the size of this dimension. */
44855d8c
TS
3795 size = fold_build2 (MINUS_EXPR, gfc_array_index_type,
3796 gfc_index_one_node, se.expr);
6de9cd9a
DN
3797
3798 /* Set upper bound. */
3799 gfc_init_se (&se, NULL);
6e45f57b 3800 gcc_assert (ubound);
6de9cd9a
DN
3801 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
3802 gfc_add_block_to_block (pblock, &se.pre);
3803
3804 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
726a989a 3805 gfc_add_modify (pblock, tmp, se.expr);
6de9cd9a
DN
3806
3807 /* Store the stride. */
3808 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
726a989a 3809 gfc_add_modify (pblock, tmp, stride);
6de9cd9a
DN
3810
3811 /* Calculate the size of this dimension. */
10c7a96f 3812 size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
6de9cd9a 3813
dbfd1e01 3814 /* Check whether the size for this dimension is negative. */
3c86fb4e
TK
3815 cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3816 gfc_index_zero_node);
3817 if (n == 0)
3818 or_expr = cond;
3819 else
3820 or_expr = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, or_expr, cond);
3821
067feae3
PT
3822 size = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
3823 gfc_index_zero_node, size);
3824
6de9cd9a 3825 /* Multiply the stride by the number of elements in this dimension. */
10c7a96f 3826 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, size);
6de9cd9a
DN
3827 stride = gfc_evaluate_now (stride, pblock);
3828 }
3829
3830 /* The stride is the number of elements in the array, so multiply by the
3831 size of an element to get the total size. */
3832 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
7c57b2f1
FXC
3833 size = fold_build2 (MULT_EXPR, gfc_array_index_type, stride,
3834 fold_convert (gfc_array_index_type, tmp));
6de9cd9a
DN
3835
3836 if (poffset != NULL)
3837 {
3838 offset = gfc_evaluate_now (offset, pblock);
3839 *poffset = offset;
3840 }
3841
fcac9229
RS
3842 if (integer_zerop (or_expr))
3843 return size;
3844 if (integer_onep (or_expr))
3845 return gfc_index_zero_node;
3846
3c86fb4e
TK
3847 var = gfc_create_var (TREE_TYPE (size), "size");
3848 gfc_start_block (&thenblock);
726a989a 3849 gfc_add_modify (&thenblock, var, gfc_index_zero_node);
3c86fb4e
TK
3850 thencase = gfc_finish_block (&thenblock);
3851
3852 gfc_start_block (&elseblock);
726a989a 3853 gfc_add_modify (&elseblock, var, size);
3c86fb4e
TK
3854 elsecase = gfc_finish_block (&elseblock);
3855
3856 tmp = gfc_evaluate_now (or_expr, pblock);
3857 tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);
3858 gfc_add_expr_to_block (pblock, tmp);
3859
3860 return var;
6de9cd9a
DN
3861}
3862
3863
1f2959f0 3864/* Initializes the descriptor and generates a call to _gfor_allocate. Does
6de9cd9a
DN
3865 the work for an ALLOCATE statement. */
3866/*GCC ARRAYS*/
3867
5b725b8d
TK
3868bool
3869gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
6de9cd9a
DN
3870{
3871 tree tmp;
3872 tree pointer;
6de9cd9a
DN
3873 tree offset;
3874 tree size;
3875 gfc_expr **lower;
3876 gfc_expr **upper;
5046aff5
PT
3877 gfc_ref *ref, *prev_ref = NULL;
3878 bool allocatable_array;
5b725b8d
TK
3879
3880 ref = expr->ref;
3881
3882 /* Find the last reference in the chain. */
3883 while (ref && ref->next != NULL)
3884 {
3885 gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
5046aff5 3886 prev_ref = ref;
5b725b8d
TK
3887 ref = ref->next;
3888 }
3889
3890 if (ref == NULL || ref->type != REF_ARRAY)
3891 return false;
6de9cd9a 3892
5046aff5
PT
3893 if (!prev_ref)
3894 allocatable_array = expr->symtree->n.sym->attr.allocatable;
3895 else
d4b7d0f0 3896 allocatable_array = prev_ref->u.c.component->attr.allocatable;
5046aff5 3897
6de9cd9a
DN
3898 /* Figure out the size of the array. */
3899 switch (ref->u.ar.type)
3900 {
3901 case AR_ELEMENT:
3902 lower = NULL;
3903 upper = ref->u.ar.start;
3904 break;
3905
3906 case AR_FULL:
6e45f57b 3907 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
6de9cd9a
DN
3908
3909 lower = ref->u.ar.as->lower;
3910 upper = ref->u.ar.as->upper;
3911 break;
3912
3913 case AR_SECTION:
3914 lower = ref->u.ar.start;
3915 upper = ref->u.ar.end;
3916 break;
3917
3918 default:
6e45f57b 3919 gcc_unreachable ();
6de9cd9a
DN
3920 break;
3921 }
3922
3923 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
3924 lower, upper, &se->pre);
3925
3926 /* Allocate memory to store the data. */
54200abb
RG
3927 pointer = gfc_conv_descriptor_data_get (se->expr);
3928 STRIP_NOPS (pointer);
6de9cd9a 3929
54200abb
RG
3930 /* The allocate_array variants take the old pointer as first argument. */
3931 if (allocatable_array)
f25a62a5 3932 tmp = gfc_allocate_array_with_status (&se->pre, pointer, size, pstat, expr);
5039610b 3933 else
4376b7cf 3934 tmp = gfc_allocate_with_status (&se->pre, size, pstat);
44855d8c 3935 tmp = fold_build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
6de9cd9a
DN
3936 gfc_add_expr_to_block (&se->pre, tmp);
3937
6de9cd9a 3938 tmp = gfc_conv_descriptor_offset (se->expr);
726a989a 3939 gfc_add_modify (&se->pre, tmp, offset);
5b725b8d 3940
5046aff5
PT
3941 if (expr->ts.type == BT_DERIVED
3942 && expr->ts.derived->attr.alloc_comp)
3943 {
3944 tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
3945 ref->u.ar.as->rank);
3946 gfc_add_expr_to_block (&se->pre, tmp);
3947 }
3948
5b725b8d 3949 return true;
6de9cd9a
DN
3950}
3951
3952
3953/* Deallocate an array variable. Also used when an allocated variable goes
3954 out of scope. */
3955/*GCC ARRAYS*/
3956
3957tree
f25a62a5 3958gfc_array_deallocate (tree descriptor, tree pstat, gfc_expr* expr)
6de9cd9a
DN
3959{
3960 tree var;
3961 tree tmp;
3962 stmtblock_t block;
3963
3964 gfc_start_block (&block);
3965 /* Get a pointer to the data. */
54200abb
RG
3966 var = gfc_conv_descriptor_data_get (descriptor);
3967 STRIP_NOPS (var);
6de9cd9a
DN
3968
3969 /* Parameter is the address of the data component. */
f25a62a5 3970 tmp = gfc_deallocate_with_status (var, pstat, false, expr);
6de9cd9a
DN
3971 gfc_add_expr_to_block (&block, tmp);
3972
54200abb 3973 /* Zero the data pointer. */
44855d8c
TS
3974 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
3975 var, build_int_cst (TREE_TYPE (var), 0));
54200abb
RG
3976 gfc_add_expr_to_block (&block, tmp);
3977
6de9cd9a
DN
3978 return gfc_finish_block (&block);
3979}
3980
3981
3982/* Create an array constructor from an initialization expression.
3983 We assume the frontend already did any expansions and conversions. */
3984
3985tree
3986gfc_conv_array_initializer (tree type, gfc_expr * expr)
3987{
3988 gfc_constructor *c;
6de9cd9a
DN
3989 tree tmp;
3990 mpz_t maxval;
3991 gfc_se se;
3992 HOST_WIDE_INT hi;
3993 unsigned HOST_WIDE_INT lo;
3994 tree index, range;
4038c495 3995 VEC(constructor_elt,gc) *v = NULL;
6de9cd9a 3996
6de9cd9a
DN
3997 switch (expr->expr_type)
3998 {
3999 case EXPR_CONSTANT:
4000 case EXPR_STRUCTURE:
4001 /* A single scalar or derived type value. Create an array with all
4002 elements equal to that value. */
4003 gfc_init_se (&se, NULL);
e9cfef64
PB
4004
4005 if (expr->expr_type == EXPR_CONSTANT)
4006 gfc_conv_constant (&se, expr);
4007 else
4008 gfc_conv_structure (&se, expr, 1);
6de9cd9a
DN
4009
4010 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
6e45f57b 4011 gcc_assert (tmp && INTEGER_CST_P (tmp));
6de9cd9a
DN
4012 hi = TREE_INT_CST_HIGH (tmp);
4013 lo = TREE_INT_CST_LOW (tmp);
4014 lo++;
4015 if (lo == 0)
4016 hi++;
4017 /* This will probably eat buckets of memory for large arrays. */
4018 while (hi != 0 || lo != 0)
4019 {
4038c495 4020 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, se.expr);
6de9cd9a
DN
4021 if (lo == 0)
4022 hi--;
4023 lo--;
4024 }
4025 break;
4026
4027 case EXPR_ARRAY:
4038c495 4028 /* Create a vector of all the elements. */
6de9cd9a
DN
4029 for (c = expr->value.constructor; c; c = c->next)
4030 {
4031 if (c->iterator)
4032 {
4033 /* Problems occur when we get something like
63346ddb
SK
4034 integer :: a(lots) = (/(i, i=1, lots)/) */
4035 gfc_error_now ("The number of elements in the array constructor "
4036 "at %L requires an increase of the allowed %d "
4037 "upper limit. See -fmax-array-constructor "
4038 "option", &expr->where,
4039 gfc_option.flag_max_array_constructor);
4040 return NULL_TREE;
6de9cd9a
DN
4041 }
4042 if (mpz_cmp_si (c->n.offset, 0) != 0)
4043 index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
4044 else
4045 index = NULL_TREE;
4046 mpz_init (maxval);
4047 if (mpz_cmp_si (c->repeat, 0) != 0)
4048 {
4049 tree tmp1, tmp2;
4050
4051 mpz_set (maxval, c->repeat);
4052 mpz_add (maxval, c->n.offset, maxval);
4053 mpz_sub_ui (maxval, maxval, 1);
4054 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
4055 if (mpz_cmp_si (c->n.offset, 0) != 0)
4056 {
4057 mpz_add_ui (maxval, c->n.offset, 1);
4058 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
4059 }
4060 else
4061 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
4062
44855d8c 4063 range = fold_build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
6de9cd9a
DN
4064 }
4065 else
4066 range = NULL;
4067 mpz_clear (maxval);
4068
4069 gfc_init_se (&se, NULL);
4070 switch (c->expr->expr_type)
4071 {
4072 case EXPR_CONSTANT:
4073 gfc_conv_constant (&se, c->expr);
4074 if (range == NULL_TREE)
4038c495 4075 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6de9cd9a
DN
4076 else
4077 {
4078 if (index != NULL_TREE)
4038c495
GB
4079 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4080 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
6de9cd9a
DN
4081 }
4082 break;
4083
4084 case EXPR_STRUCTURE:
4085 gfc_conv_structure (&se, c->expr, 1);
4038c495 4086 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
6de9cd9a
DN
4087 break;
4088
c1cfed03 4089
6de9cd9a 4090 default:
c1cfed03
PT
4091 /* Catch those occasional beasts that do not simplify
4092 for one reason or another, assuming that if they are
4093 standard defying the frontend will catch them. */
4094 gfc_conv_expr (&se, c->expr);
4095 if (range == NULL_TREE)
4096 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4097 else
4098 {
4099 if (index != NULL_TREE)
4100 CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
4101 CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
4102 }
4103 break;
6de9cd9a
DN
4104 }
4105 }
6de9cd9a
DN
4106 break;
4107
5046aff5
PT
4108 case EXPR_NULL:
4109 return gfc_build_null_descriptor (type);
4110
6de9cd9a 4111 default:
6e45f57b 4112 gcc_unreachable ();
6de9cd9a
DN
4113 }
4114
4115 /* Create a constructor from the list of elements. */
4038c495 4116 tmp = build_constructor (type, v);
6de9cd9a 4117 TREE_CONSTANT (tmp) = 1;
6de9cd9a
DN
4118 return tmp;
4119}
4120
4121
4122/* Generate code to evaluate non-constant array bounds. Sets *poffset and
4123 returns the size (in elements) of the array. */
4124
4125static tree
4126gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
4127 stmtblock_t * pblock)
4128{
4129 gfc_array_spec *as;
4130 tree size;
4131 tree stride;
4132 tree offset;
4133 tree ubound;
4134 tree lbound;
4135 tree tmp;
4136 gfc_se se;
4137
4138 int dim;
4139
4140 as = sym->as;
4141
7ab92584
SB
4142 size = gfc_index_one_node;
4143 offset = gfc_index_zero_node;
6de9cd9a
DN
4144 for (dim = 0; dim < as->rank; dim++)
4145 {
4146 /* Evaluate non-constant array bound expressions. */
4147 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
4148 if (as->lower[dim] && !INTEGER_CST_P (lbound))
4149 {
4150 gfc_init_se (&se, NULL);
4151 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
4152 gfc_add_block_to_block (pblock, &se.pre);
726a989a 4153 gfc_add_modify (pblock, lbound, se.expr);
6de9cd9a
DN
4154 }
4155 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
4156 if (as->upper[dim] && !INTEGER_CST_P (ubound))
4157 {
4158 gfc_init_se (&se, NULL);
4159 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
4160 gfc_add_block_to_block (pblock, &se.pre);
726a989a 4161 gfc_add_modify (pblock, ubound, se.expr);
6de9cd9a 4162 }
f7b529fa 4163 /* The offset of this dimension. offset = offset - lbound * stride. */
10c7a96f
SB
4164 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, size);
4165 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
6de9cd9a
DN
4166
4167 /* The size of this dimension, and the stride of the next. */
4168 if (dim + 1 < as->rank)
4169 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
4170 else
417ab240 4171 stride = GFC_TYPE_ARRAY_SIZE (type);
6de9cd9a
DN
4172
4173 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
4174 {
4175 /* Calculate stride = size * (ubound + 1 - lbound). */
10c7a96f
SB
4176 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4177 gfc_index_one_node, lbound);
4178 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp);
4179 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
6de9cd9a 4180 if (stride)
726a989a 4181 gfc_add_modify (pblock, stride, tmp);
6de9cd9a
DN
4182 else
4183 stride = gfc_evaluate_now (tmp, pblock);
5b440a1c
PT
4184
4185 /* Make sure that negative size arrays are translated
4186 to being zero size. */
44855d8c
TS
4187 tmp = fold_build2 (GE_EXPR, boolean_type_node,
4188 stride, gfc_index_zero_node);
4189 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, tmp,
4190 stride, gfc_index_zero_node);
726a989a 4191 gfc_add_modify (pblock, stride, tmp);
6de9cd9a
DN
4192 }
4193
4194 size = stride;
4195 }
4196
417ab240
JJ
4197 gfc_trans_vla_type_sizes (sym, pblock);
4198
6de9cd9a
DN
4199 *poffset = offset;
4200 return size;
4201}
4202
4203
4204/* Generate code to initialize/allocate an array variable. */
4205
4206tree
4207gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
4208{
4209 stmtblock_t block;
4210 tree type;
4211 tree tmp;
6de9cd9a
DN
4212 tree size;
4213 tree offset;
6de9cd9a
DN
4214 bool onstack;
4215
6e45f57b 4216 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
6de9cd9a
DN
4217
4218 /* Do nothing for USEd variables. */
4219 if (sym->attr.use_assoc)
4220 return fnbody;
4221
4222 type = TREE_TYPE (decl);
6e45f57b 4223 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a
DN
4224 onstack = TREE_CODE (type) != POINTER_TYPE;
4225
6de9cd9a
DN
4226 gfc_start_block (&block);
4227
4228 /* Evaluate character string length. */
4229 if (sym->ts.type == BT_CHARACTER
4230 && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4231 {
4b7f8314 4232 gfc_conv_string_length (sym->ts.cl, NULL, &block);
6de9cd9a 4233
417ab240
JJ
4234 gfc_trans_vla_type_sizes (sym, &block);
4235
1a186ec5 4236 /* Emit a DECL_EXPR for this variable, which will cause the
13795658 4237 gimplifier to allocate storage, and all that good stuff. */
44855d8c 4238 tmp = fold_build1 (DECL_EXPR, TREE_TYPE (decl), decl);
6de9cd9a
DN
4239 gfc_add_expr_to_block (&block, tmp);
4240 }
4241
4242 if (onstack)
4243 {
6de9cd9a
DN
4244 gfc_add_expr_to_block (&block, fnbody);
4245 return gfc_finish_block (&block);
4246 }
4247
4248 type = TREE_TYPE (type);
4249
6e45f57b
PB
4250 gcc_assert (!sym->attr.use_assoc);
4251 gcc_assert (!TREE_STATIC (decl));
cb9e4f55 4252 gcc_assert (!sym->module);
6de9cd9a
DN
4253
4254 if (sym->ts.type == BT_CHARACTER
4255 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
4b7f8314 4256 gfc_conv_string_length (sym->ts.cl, NULL, &block);
6de9cd9a
DN
4257
4258 size = gfc_trans_array_bounds (type, sym, &offset, &block);
4259
83d890b9
AL
4260 /* Don't actually allocate space for Cray Pointees. */
4261 if (sym->attr.cray_pointee)
4262 {
4263 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
726a989a 4264 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
83d890b9
AL
4265 gfc_add_expr_to_block (&block, fnbody);
4266 return gfc_finish_block (&block);
4267 }
4268
6de9cd9a
DN
4269 /* The size is the number of elements in the array, so multiply by the
4270 size of an element to get the total size. */
4271 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
61f70bf2
FXC
4272 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
4273 fold_convert (gfc_array_index_type, tmp));
6de9cd9a
DN
4274
4275 /* Allocate memory to hold the data. */
1529b8d9 4276 tmp = gfc_call_malloc (&block, TREE_TYPE (decl), size);
726a989a 4277 gfc_add_modify (&block, decl, tmp);
6de9cd9a
DN
4278
4279 /* Set offset of the array. */
4280 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
726a989a 4281 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
6de9cd9a
DN
4282
4283
4284 /* Automatic arrays should not have initializers. */
6e45f57b 4285 gcc_assert (!sym->value);
6de9cd9a
DN
4286
4287 gfc_add_expr_to_block (&block, fnbody);
4288
4289 /* Free the temporary. */
1529b8d9 4290 tmp = gfc_call_free (convert (pvoid_type_node, decl));
6de9cd9a
DN
4291 gfc_add_expr_to_block (&block, tmp);
4292
4293 return gfc_finish_block (&block);
4294}
4295
4296
4297/* Generate entry and exit code for g77 calling convention arrays. */
4298
4299tree
4300gfc_trans_g77_array (gfc_symbol * sym, tree body)
4301{
4302 tree parm;
4303 tree type;
4304 locus loc;
4305 tree offset;
4306 tree tmp;
54129a64 4307 tree stmt;
6de9cd9a
DN
4308 stmtblock_t block;
4309
4310 gfc_get_backend_locus (&loc);
4311 gfc_set_backend_locus (&sym->declared_at);
4312
4313 /* Descriptor type. */
4314 parm = sym->backend_decl;
4315 type = TREE_TYPE (parm);
6e45f57b 4316 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a
DN
4317
4318 gfc_start_block (&block);
4319
4320 if (sym->ts.type == BT_CHARACTER
20c9dc8a 4321 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4b7f8314 4322 gfc_conv_string_length (sym->ts.cl, NULL, &block);
6de9cd9a
DN
4323
4324 /* Evaluate the bounds of the array. */
4325 gfc_trans_array_bounds (type, sym, &offset, &block);
4326
4327 /* Set the offset. */
4328 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
726a989a 4329 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
6de9cd9a 4330
1f2959f0 4331 /* Set the pointer itself if we aren't using the parameter directly. */
6de9cd9a
DN
4332 if (TREE_CODE (parm) != PARM_DECL)
4333 {
4334 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
726a989a 4335 gfc_add_modify (&block, parm, tmp);
6de9cd9a 4336 }
54129a64 4337 stmt = gfc_finish_block (&block);
6de9cd9a
DN
4338
4339 gfc_set_backend_locus (&loc);
4340
4341 gfc_start_block (&block);
54129a64 4342
6de9cd9a 4343 /* Add the initialization code to the start of the function. */
54129a64
PT
4344
4345 if (sym->attr.optional || sym->attr.not_always_present)
4346 {
4347 tmp = gfc_conv_expr_present (sym);
4348 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
4349 }
4350
4351 gfc_add_expr_to_block (&block, stmt);
6de9cd9a
DN
4352 gfc_add_expr_to_block (&block, body);
4353
4354 return gfc_finish_block (&block);
4355}
4356
4357
4358/* Modify the descriptor of an array parameter so that it has the
4359 correct lower bound. Also move the upper bound accordingly.
4360 If the array is not packed, it will be copied into a temporary.
4361 For each dimension we set the new lower and upper bounds. Then we copy the
4362 stride and calculate the offset for this dimension. We also work out
4363 what the stride of a packed array would be, and see it the two match.
4364 If the array need repacking, we set the stride to the values we just
4365 calculated, recalculate the offset and copy the array data.
4366 Code is also added to copy the data back at the end of the function.
4367 */
4368
4369tree
4370gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
4371{
4372 tree size;
4373 tree type;
4374 tree offset;
4375 locus loc;
4376 stmtblock_t block;
4377 stmtblock_t cleanup;
4378 tree lbound;
4379 tree ubound;
4380 tree dubound;
4381 tree dlbound;
4382 tree dumdesc;
4383 tree tmp;
4384 tree stmt;
e8300d6e 4385 tree stride, stride2;
6de9cd9a
DN
4386 tree stmt_packed;
4387 tree stmt_unpacked;
4388 tree partial;
4389 gfc_se se;
4390 int n;
4391 int checkparm;
4392 int no_repack;
3d79abbd 4393 bool optional_arg;
6de9cd9a 4394
fc90a8f2
PB
4395 /* Do nothing for pointer and allocatable arrays. */
4396 if (sym->attr.pointer || sym->attr.allocatable)
4397 return body;
4398
6de9cd9a
DN
4399 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
4400 return gfc_trans_g77_array (sym, body);
4401
4402 gfc_get_backend_locus (&loc);
4403 gfc_set_backend_locus (&sym->declared_at);
4404
4405 /* Descriptor type. */
4406 type = TREE_TYPE (tmpdesc);
6e45f57b 4407 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a 4408 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
38611275 4409 dumdesc = build_fold_indirect_ref (dumdesc);
6de9cd9a
DN
4410 gfc_start_block (&block);
4411
4412 if (sym->ts.type == BT_CHARACTER
20c9dc8a 4413 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
4b7f8314 4414 gfc_conv_string_length (sym->ts.cl, NULL, &block);
6de9cd9a 4415
d3d3011f
FXC
4416 checkparm = (sym->as->type == AS_EXPLICIT
4417 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
6de9cd9a
DN
4418
4419 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
4420 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
4421
4422 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
4423 {
4424 /* For non-constant shape arrays we only check if the first dimension
4425 is contiguous. Repacking higher dimensions wouldn't gain us
4426 anything as we still don't know the array stride. */
4427 partial = gfc_create_var (boolean_type_node, "partial");
4428 TREE_USED (partial) = 1;
4429 tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
37da9343 4430 tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
726a989a 4431 gfc_add_modify (&block, partial, tmp);
6de9cd9a
DN
4432 }
4433 else
4434 {
4435 partial = NULL_TREE;
4436 }
4437
4438 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
4439 here, however I think it does the right thing. */
4440 if (no_repack)
4441 {
4442 /* Set the first stride. */
4443 stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
4444 stride = gfc_evaluate_now (stride, &block);
4445
44855d8c
TS
4446 tmp = fold_build2 (EQ_EXPR, boolean_type_node,
4447 stride, gfc_index_zero_node);
4448 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, tmp,
4449 gfc_index_one_node, stride);
6de9cd9a 4450 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
726a989a 4451 gfc_add_modify (&block, stride, tmp);
6de9cd9a
DN
4452
4453 /* Allow the user to disable array repacking. */
4454 stmt_unpacked = NULL_TREE;
4455 }
4456 else
4457 {
6e45f57b 4458 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
1f2959f0 4459 /* A library call to repack the array if necessary. */
6de9cd9a 4460 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
5039610b 4461 stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
6de9cd9a 4462
7ab92584 4463 stride = gfc_index_one_node;
bdfd2ff0
TK
4464
4465 if (gfc_option.warn_array_temp)
4466 gfc_warning ("Creating array temporary at %L", &loc);
6de9cd9a
DN
4467 }
4468
4469 /* This is for the case where the array data is used directly without
4470 calling the repack function. */
4471 if (no_repack || partial != NULL_TREE)
4c73896d 4472 stmt_packed = gfc_conv_descriptor_data_get (dumdesc);
6de9cd9a
DN
4473 else
4474 stmt_packed = NULL_TREE;
4475
4476 /* Assign the data pointer. */
4477 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
4478 {
4479 /* Don't repack unknown shape arrays when the first stride is 1. */
44855d8c
TS
4480 tmp = fold_build3 (COND_EXPR, TREE_TYPE (stmt_packed),
4481 partial, stmt_packed, stmt_unpacked);
6de9cd9a
DN
4482 }
4483 else
4484 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
726a989a 4485 gfc_add_modify (&block, tmpdesc, fold_convert (type, tmp));
6de9cd9a 4486
7ab92584
SB
4487 offset = gfc_index_zero_node;
4488 size = gfc_index_one_node;
6de9cd9a
DN
4489
4490 /* Evaluate the bounds of the array. */
4491 for (n = 0; n < sym->as->rank; n++)
4492 {
4493 if (checkparm || !sym->as->upper[n])
4494 {
4495 /* Get the bounds of the actual parameter. */
4496 dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
4497 dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
4498 }
4499 else
4500 {
4501 dubound = NULL_TREE;
4502 dlbound = NULL_TREE;
4503 }
4504
4505 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
4506 if (!INTEGER_CST_P (lbound))
4507 {
4508 gfc_init_se (&se, NULL);
0df3cf7f 4509 gfc_conv_expr_type (&se, sym->as->lower[n],
6de9cd9a
DN
4510 gfc_array_index_type);
4511 gfc_add_block_to_block (&block, &se.pre);
726a989a 4512 gfc_add_modify (&block, lbound, se.expr);
6de9cd9a
DN
4513 }
4514
4515 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
4516 /* Set the desired upper bound. */
4517 if (sym->as->upper[n])
4518 {
4519 /* We know what we want the upper bound to be. */
4520 if (!INTEGER_CST_P (ubound))
4521 {
4522 gfc_init_se (&se, NULL);
4523 gfc_conv_expr_type (&se, sym->as->upper[n],
4524 gfc_array_index_type);
4525 gfc_add_block_to_block (&block, &se.pre);
726a989a 4526 gfc_add_modify (&block, ubound, se.expr);
6de9cd9a
DN
4527 }
4528
4529 /* Check the sizes match. */
4530 if (checkparm)
4531 {
4532 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
dd18a33b 4533 char * msg;
6de9cd9a 4534
10c7a96f
SB
4535 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4536 ubound, lbound);
44855d8c
TS
4537 stride2 = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4538 dubound, dlbound);
e8300d6e 4539 tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
dd18a33b
FXC
4540 asprintf (&msg, "%s for dimension %d of array '%s'",
4541 gfc_msg_bounds, n+1, sym->name);
0d52899f 4542 gfc_trans_runtime_check (true, false, tmp, &block, &loc, msg);
dd18a33b 4543 gfc_free (msg);
6de9cd9a
DN
4544 }
4545 }
4546 else
4547 {
4548 /* For assumed shape arrays move the upper bound by the same amount
4549 as the lower bound. */
44855d8c
TS
4550 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4551 dubound, dlbound);
10c7a96f 4552 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound);
726a989a 4553 gfc_add_modify (&block, ubound, tmp);
6de9cd9a 4554 }
f7b529fa 4555 /* The offset of this dimension. offset = offset - lbound * stride. */
10c7a96f
SB
4556 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, lbound, stride);
4557 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);
6de9cd9a
DN
4558
4559 /* The size of this dimension, and the stride of the next. */
4560 if (n + 1 < sym->as->rank)
4561 {
4562 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
4563
4564 if (no_repack || partial != NULL_TREE)
4565 {
4566 stmt_unpacked =
4567 gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
4568 }
4569
4570 /* Figure out the stride if not a known constant. */
4571 if (!INTEGER_CST_P (stride))
4572 {
4573 if (no_repack)
4574 stmt_packed = NULL_TREE;
4575 else
4576 {
4577 /* Calculate stride = size * (ubound + 1 - lbound). */
10c7a96f
SB
4578 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4579 gfc_index_one_node, lbound);
4580 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4581 ubound, tmp);
4582 size = fold_build2 (MULT_EXPR, gfc_array_index_type,
4583 size, tmp);
6de9cd9a
DN
4584 stmt_packed = size;
4585 }
4586
4587 /* Assign the stride. */
4588 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
44855d8c
TS
4589 tmp = fold_build3 (COND_EXPR, gfc_array_index_type, partial,
4590 stmt_unpacked, stmt_packed);
6de9cd9a
DN
4591 else
4592 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
726a989a 4593 gfc_add_modify (&block, stride, tmp);
6de9cd9a
DN
4594 }
4595 }
417ab240
JJ
4596 else
4597 {
4598 stride = GFC_TYPE_ARRAY_SIZE (type);
4599
4600 if (stride && !INTEGER_CST_P (stride))
4601 {
4602 /* Calculate size = stride * (ubound + 1 - lbound). */
4603 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
4604 gfc_index_one_node, lbound);
4605 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4606 ubound, tmp);
4607 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
4608 GFC_TYPE_ARRAY_STRIDE (type, n), tmp);
726a989a 4609 gfc_add_modify (&block, stride, tmp);
417ab240
JJ
4610 }
4611 }
6de9cd9a
DN
4612 }
4613
4614 /* Set the offset. */
4615 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
726a989a 4616 gfc_add_modify (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
6de9cd9a 4617
417ab240
JJ
4618 gfc_trans_vla_type_sizes (sym, &block);
4619
6de9cd9a
DN
4620 stmt = gfc_finish_block (&block);
4621
4622 gfc_start_block (&block);
4623
4624 /* Only do the entry/initialization code if the arg is present. */
4625 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
d198b59a
JJ
4626 optional_arg = (sym->attr.optional
4627 || (sym->ns->proc_name->attr.entry_master
4628 && sym->attr.dummy));
3d79abbd 4629 if (optional_arg)
6de9cd9a
DN
4630 {
4631 tmp = gfc_conv_expr_present (sym);
923ab88c 4632 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a
DN
4633 }
4634 gfc_add_expr_to_block (&block, stmt);
4635
4636 /* Add the main function body. */
4637 gfc_add_expr_to_block (&block, body);
4638
4639 /* Cleanup code. */
4640 if (!no_repack)
4641 {
4642 gfc_start_block (&cleanup);
4643
4644 if (sym->attr.intent != INTENT_IN)
4645 {
4646 /* Copy the data back. */
5039610b 4647 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
6de9cd9a
DN
4648 gfc_add_expr_to_block (&cleanup, tmp);
4649 }
4650
4651 /* Free the temporary. */
1529b8d9 4652 tmp = gfc_call_free (tmpdesc);
6de9cd9a
DN
4653 gfc_add_expr_to_block (&cleanup, tmp);
4654
4655 stmt = gfc_finish_block (&cleanup);
4656
4657 /* Only do the cleanup if the array was repacked. */
38611275 4658 tmp = build_fold_indirect_ref (dumdesc);
4c73896d 4659 tmp = gfc_conv_descriptor_data_get (tmp);
44855d8c 4660 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
923ab88c 4661 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a 4662
3d79abbd 4663 if (optional_arg)
6de9cd9a
DN
4664 {
4665 tmp = gfc_conv_expr_present (sym);
923ab88c 4666 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a
DN
4667 }
4668 gfc_add_expr_to_block (&block, stmt);
4669 }
4670 /* We don't need to free any memory allocated by internal_pack as it will
4671 be freed at the end of the function by pop_context. */
4672 return gfc_finish_block (&block);
4673}
4674
4675
1d6b7f39
PT
4676/* Calculate the overall offset, including subreferences. */
4677static void
4678gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
4679 bool subref, gfc_expr *expr)
4680{
4681 tree tmp;
4682 tree field;
4683 tree stride;
4684 tree index;
4685 gfc_ref *ref;
4686 gfc_se start;
4687 int n;
4688
4689 /* If offset is NULL and this is not a subreferenced array, there is
4690 nothing to do. */
4691 if (offset == NULL_TREE)
4692 {
4693 if (subref)
4694 offset = gfc_index_zero_node;
4695 else
4696 return;
4697 }
4698
4699 tmp = gfc_conv_array_data (desc);
4700 tmp = build_fold_indirect_ref (tmp);
4701 tmp = gfc_build_array_ref (tmp, offset, NULL);
4702
4703 /* Offset the data pointer for pointer assignments from arrays with
df2fba9e 4704 subreferences; e.g. my_integer => my_type(:)%integer_component. */
1d6b7f39
PT
4705 if (subref)
4706 {
4707 /* Go past the array reference. */
4708 for (ref = expr->ref; ref; ref = ref->next)
4709 if (ref->type == REF_ARRAY &&
4710 ref->u.ar.type != AR_ELEMENT)
4711 {
4712 ref = ref->next;
4713 break;
4714 }
4715
4716 /* Calculate the offset for each subsequent subreference. */
4717 for (; ref; ref = ref->next)
4718 {
4719 switch (ref->type)
4720 {
4721 case REF_COMPONENT:
4722 field = ref->u.c.component->backend_decl;
4723 gcc_assert (field && TREE_CODE (field) == FIELD_DECL);
44855d8c
TS
4724 tmp = fold_build3 (COMPONENT_REF, TREE_TYPE (field),
4725 tmp, field, NULL_TREE);
1d6b7f39
PT
4726 break;
4727
4728 case REF_SUBSTRING:
4729 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE);
4730 gfc_init_se (&start, NULL);
4731 gfc_conv_expr_type (&start, ref->u.ss.start, gfc_charlen_type_node);
4732 gfc_add_block_to_block (block, &start.pre);
4733 tmp = gfc_build_array_ref (tmp, start.expr, NULL);
4734 break;
4735
4736 case REF_ARRAY:
4737 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE
4738 && ref->u.ar.type == AR_ELEMENT);
4739
4740 /* TODO - Add bounds checking. */
4741 stride = gfc_index_one_node;
4742 index = gfc_index_zero_node;
4743 for (n = 0; n < ref->u.ar.dimen; n++)
4744 {
4745 tree itmp;
4746 tree jtmp;
4747
4748 /* Update the index. */
4749 gfc_init_se (&start, NULL);
4750 gfc_conv_expr_type (&start, ref->u.ar.start[n], gfc_array_index_type);
4751 itmp = gfc_evaluate_now (start.expr, block);
4752 gfc_init_se (&start, NULL);
4753 gfc_conv_expr_type (&start, ref->u.ar.as->lower[n], gfc_array_index_type);
4754 jtmp = gfc_evaluate_now (start.expr, block);
4755 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, itmp, jtmp);
4756 itmp = fold_build2 (MULT_EXPR, gfc_array_index_type, itmp, stride);
4757 index = fold_build2 (PLUS_EXPR, gfc_array_index_type, itmp, index);
4758 index = gfc_evaluate_now (index, block);
4759
4760 /* Update the stride. */
4761 gfc_init_se (&start, NULL);
4762 gfc_conv_expr_type (&start, ref->u.ar.as->upper[n], gfc_array_index_type);
4763 itmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, start.expr, jtmp);
4764 itmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
4765 gfc_index_one_node, itmp);
4766 stride = fold_build2 (MULT_EXPR, gfc_array_index_type, stride, itmp);
4767 stride = gfc_evaluate_now (stride, block);
4768 }
4769
4770 /* Apply the index to obtain the array element. */
4771 tmp = gfc_build_array_ref (tmp, index, NULL);
4772 break;
4773
4774 default:
4775 gcc_unreachable ();
4776 break;
4777 }
4778 }
4779 }
4780
4781 /* Set the target data pointer. */
4782 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
4783 gfc_conv_descriptor_data_set (block, parm, offset);
4784}
4785
4786
5d63a35f
PT
4787/* gfc_conv_expr_descriptor needs the string length an expression
4788 so that the size of the temporary can be obtained. This is done
4789 by adding up the string lengths of all the elements in the
4790 expression. Function with non-constant expressions have their
4791 string lengths mapped onto the actual arguments using the
4792 interface mapping machinery in trans-expr.c. */
0a164a3c 4793static void
5d63a35f 4794get_array_charlen (gfc_expr *expr, gfc_se *se)
0a164a3c
PT
4795{
4796 gfc_interface_mapping mapping;
4797 gfc_formal_arglist *formal;
4798 gfc_actual_arglist *arg;
4799 gfc_se tse;
4800
5d63a35f
PT
4801 if (expr->ts.cl->length
4802 && gfc_is_constant_expr (expr->ts.cl->length))
0a164a3c 4803 {
5d63a35f
PT
4804 if (!expr->ts.cl->backend_decl)
4805 gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
4806 return;
0a164a3c
PT
4807 }
4808
5d63a35f
PT
4809 switch (expr->expr_type)
4810 {
4811 case EXPR_OP:
4812 get_array_charlen (expr->value.op.op1, se);
4813
4814 /* For parentheses the expression ts.cl is identical. */
4815 if (expr->value.op.op == INTRINSIC_PARENTHESES)
4816 return;
4817
4818 expr->ts.cl->backend_decl =
4819 gfc_create_var (gfc_charlen_type_node, "sln");
4820
4821 if (expr->value.op.op2)
4822 {
4823 get_array_charlen (expr->value.op.op2, se);
4824
71a7778c
PT
4825 gcc_assert (expr->value.op.op == INTRINSIC_CONCAT);
4826
5d63a35f
PT
4827 /* Add the string lengths and assign them to the expression
4828 string length backend declaration. */
4829 gfc_add_modify (&se->pre, expr->ts.cl->backend_decl,
4830 fold_build2 (PLUS_EXPR, gfc_charlen_type_node,
4831 expr->value.op.op1->ts.cl->backend_decl,
4832 expr->value.op.op2->ts.cl->backend_decl));
4833 }
4834 else
4835 gfc_add_modify (&se->pre, expr->ts.cl->backend_decl,
4836 expr->value.op.op1->ts.cl->backend_decl);
4837 break;
4838
4839 case EXPR_FUNCTION:
4840 if (expr->value.function.esym == NULL
4841 || expr->ts.cl->length->expr_type == EXPR_CONSTANT)
4842 {
4843 gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
4844 break;
4845 }
4846
4847 /* Map expressions involving the dummy arguments onto the actual
4848 argument expressions. */
4849 gfc_init_interface_mapping (&mapping);
4850 formal = expr->symtree->n.sym->formal;
4851 arg = expr->value.function.actual;
4852
4853 /* Set se = NULL in the calls to the interface mapping, to suppress any
4854 backend stuff. */
4855 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
4856 {
4857 if (!arg->expr)
4858 continue;
4859 if (formal->sym)
4860 gfc_add_interface_mapping (&mapping, formal->sym, NULL, arg->expr);
4861 }
4862
4863 gfc_init_se (&tse, NULL);
4864
4865 /* Build the expression for the character length and convert it. */
4866 gfc_apply_interface_mapping (&mapping, &tse, expr->ts.cl->length);
0a164a3c 4867
5d63a35f
PT
4868 gfc_add_block_to_block (&se->pre, &tse.pre);
4869 gfc_add_block_to_block (&se->post, &tse.post);
4870 tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
4871 tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
4872 build_int_cst (gfc_charlen_type_node, 0));
4873 expr->ts.cl->backend_decl = tse.expr;
4874 gfc_free_interface_mapping (&mapping);
4875 break;
0a164a3c 4876
5d63a35f
PT
4877 default:
4878 gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
4879 break;
4880 }
0a164a3c
PT
4881}
4882
4883
5d63a35f 4884
7a70c12d 4885/* Convert an array for passing as an actual argument. Expressions and
7ab92584 4886 vector subscripts are evaluated and stored in a temporary, which is then
6de9cd9a
DN
4887 passed. For whole arrays the descriptor is passed. For array sections
4888 a modified copy of the descriptor is passed, but using the original data.
7a70c12d
RS
4889
4890 This function is also used for array pointer assignments, and there
4891 are three cases:
4892
3e90ac4e 4893 - se->want_pointer && !se->direct_byref
7a70c12d
RS
4894 EXPR is an actual argument. On exit, se->expr contains a
4895 pointer to the array descriptor.
4896
3e90ac4e 4897 - !se->want_pointer && !se->direct_byref
7a70c12d
RS
4898 EXPR is an actual argument to an intrinsic function or the
4899 left-hand side of a pointer assignment. On exit, se->expr
4900 contains the descriptor for EXPR.
4901
3e90ac4e 4902 - !se->want_pointer && se->direct_byref
7a70c12d
RS
4903 EXPR is the right-hand side of a pointer assignment and
4904 se->expr is the descriptor for the previously-evaluated
4905 left-hand side. The function creates an assignment from
4906 EXPR to se->expr. */
6de9cd9a
DN
4907
4908void
4909gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
4910{
4911 gfc_loopinfo loop;
4912 gfc_ss *secss;
4913 gfc_ss_info *info;
4914 int need_tmp;
4915 int n;
4916 tree tmp;
4917 tree desc;
4918 stmtblock_t block;
4919 tree start;
4920 tree offset;
4921 int full;
1d6b7f39 4922 bool subref_array_target = false;
6de9cd9a 4923
6e45f57b 4924 gcc_assert (ss != gfc_ss_terminator);
6de9cd9a 4925
fc90a8f2
PB
4926 /* Special case things we know we can pass easily. */
4927 switch (expr->expr_type)
6de9cd9a 4928 {
fc90a8f2
PB
4929 case EXPR_VARIABLE:
4930 /* If we have a linear array section, we can pass it directly.
4931 Otherwise we need to copy it into a temporary. */
6de9cd9a
DN
4932
4933 /* Find the SS for the array section. */
4934 secss = ss;
4935 while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
4936 secss = secss->next;
4937
6e45f57b 4938 gcc_assert (secss != gfc_ss_terminator);
6de9cd9a
DN
4939 info = &secss->data.info;
4940
4941 /* Get the descriptor for the array. */
4942 gfc_conv_ss_descriptor (&se->pre, secss, 0);
4943 desc = info->descriptor;
7a70c12d 4944
1d6b7f39
PT
4945 subref_array_target = se->direct_byref && is_subref_array (expr);
4946 need_tmp = gfc_ref_needs_temporary_p (expr->ref)
4947 && !subref_array_target;
4948
7a70c12d
RS
4949 if (need_tmp)
4950 full = 0;
4951 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
6de9cd9a
DN
4952 {
4953 /* Create a new descriptor if the array doesn't have one. */
4954 full = 0;
4955 }
4956 else if (info->ref->u.ar.type == AR_FULL)
4957 full = 1;
4958 else if (se->direct_byref)
4959 full = 0;
4960 else
fcd44320 4961 full = gfc_full_array_ref_p (info->ref);
ca2940c3 4962
6de9cd9a
DN
4963 if (full)
4964 {
4965 if (se->direct_byref)
4966 {
4967 /* Copy the descriptor for pointer assignments. */
726a989a 4968 gfc_add_modify (&se->pre, se->expr, desc);
1d6b7f39
PT
4969
4970 /* Add any offsets from subreferences. */
4971 gfc_get_dataptr_offset (&se->pre, se->expr, desc, NULL_TREE,
4972 subref_array_target, expr);
6de9cd9a
DN
4973 }
4974 else if (se->want_pointer)
4975 {
4976 /* We pass full arrays directly. This means that pointers and
fc90a8f2 4977 allocatable arrays should also work. */
628c189e 4978 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6de9cd9a
DN
4979 }
4980 else
4981 {
4982 se->expr = desc;
4983 }
ca2940c3 4984
20c9dc8a 4985 if (expr->ts.type == BT_CHARACTER)
ca2940c3
TS
4986 se->string_length = gfc_get_expr_charlen (expr);
4987
6de9cd9a
DN
4988 return;
4989 }
fc90a8f2
PB
4990 break;
4991
4992 case EXPR_FUNCTION:
4993 /* A transformational function return value will be a temporary
4994 array descriptor. We still need to go through the scalarizer
4995 to create the descriptor. Elemental functions ar handled as
e7dc5b4f 4996 arbitrary expressions, i.e. copy to a temporary. */
fc90a8f2
PB
4997 secss = ss;
4998 /* Look for the SS for this function. */
4999 while (secss != gfc_ss_terminator
5000 && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
5001 secss = secss->next;
5002
5003 if (se->direct_byref)
5004 {
6e45f57b 5005 gcc_assert (secss != gfc_ss_terminator);
fc90a8f2
PB
5006
5007 /* For pointer assignments pass the descriptor directly. */
5008 se->ss = secss;
628c189e 5009 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
fc90a8f2
PB
5010 gfc_conv_expr (se, expr);
5011 return;
5012 }
5013
5014 if (secss == gfc_ss_terminator)
5015 {
5016 /* Elemental function. */
5017 need_tmp = 1;
0a164a3c
PT
5018 if (expr->ts.type == BT_CHARACTER
5019 && expr->ts.cl->length->expr_type != EXPR_CONSTANT)
5d63a35f 5020 get_array_charlen (expr, se);
0a164a3c 5021
fc90a8f2
PB
5022 info = NULL;
5023 }
5024 else
5025 {
5026 /* Transformational function. */
5027 info = &secss->data.info;
5028 need_tmp = 0;
5029 }
5030 break;
5031
114e4d10
RS
5032 case EXPR_ARRAY:
5033 /* Constant array constructors don't need a temporary. */
5034 if (ss->type == GFC_SS_CONSTRUCTOR
5035 && expr->ts.type != BT_CHARACTER
5036 && gfc_constant_array_constructor_p (expr->value.constructor))
5037 {
5038 need_tmp = 0;
5039 info = &ss->data.info;
5040 secss = ss;
5041 }
5042 else
5043 {
5044 need_tmp = 1;
5045 secss = NULL;
5046 info = NULL;
5047 }
5048 break;
5049
fc90a8f2
PB
5050 default:
5051 /* Something complicated. Copy it into a temporary. */
6de9cd9a
DN
5052 need_tmp = 1;
5053 secss = NULL;
5054 info = NULL;
fc90a8f2 5055 break;
6de9cd9a
DN
5056 }
5057
5058 gfc_init_loopinfo (&loop);
5059
5060 /* Associate the SS with the loop. */
5061 gfc_add_ss_to_loop (&loop, ss);
5062
13413760 5063 /* Tell the scalarizer not to bother creating loop variables, etc. */
6de9cd9a
DN
5064 if (!need_tmp)
5065 loop.array_parameter = 1;
5066 else
7a70c12d
RS
5067 /* The right-hand side of a pointer assignment mustn't use a temporary. */
5068 gcc_assert (!se->direct_byref);
6de9cd9a
DN
5069
5070 /* Setup the scalarizing loops and bounds. */
5071 gfc_conv_ss_startstride (&loop);
5072
5073 if (need_tmp)
5074 {
5075 /* Tell the scalarizer to make a temporary. */
5076 loop.temp_ss = gfc_get_ss ();
5077 loop.temp_ss->type = GFC_SS_TEMP;
5078 loop.temp_ss->next = gfc_ss_terminator;
07368af0 5079
5d63a35f
PT
5080 if (expr->ts.type == BT_CHARACTER
5081 && !expr->ts.cl->backend_decl)
5082 get_array_charlen (expr, se);
07368af0
PT
5083
5084 loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
5085
2b052ce2 5086 if (expr->ts.type == BT_CHARACTER)
07368af0 5087 loop.temp_ss->string_length = expr->ts.cl->backend_decl;
20c9dc8a 5088 else
07368af0
PT
5089 loop.temp_ss->string_length = NULL;
5090
5091 se->string_length = loop.temp_ss->string_length;
6de9cd9a
DN
5092 loop.temp_ss->data.temp.dimen = loop.dimen;
5093 gfc_add_ss_to_loop (&loop, loop.temp_ss);
5094 }
5095
bdfd2ff0 5096 gfc_conv_loop_setup (&loop, & expr->where);
6de9cd9a
DN
5097
5098 if (need_tmp)
5099 {
5100 /* Copy into a temporary and pass that. We don't need to copy the data
5101 back because expressions and vector subscripts must be INTENT_IN. */
5102 /* TODO: Optimize passing function return values. */
5103 gfc_se lse;
5104 gfc_se rse;
5105
5106 /* Start the copying loops. */
5107 gfc_mark_ss_chain_used (loop.temp_ss, 1);
5108 gfc_mark_ss_chain_used (ss, 1);
5109 gfc_start_scalarized_body (&loop, &block);
5110
5111 /* Copy each data element. */
5112 gfc_init_se (&lse, NULL);
5113 gfc_copy_loopinfo_to_se (&lse, &loop);
5114 gfc_init_se (&rse, NULL);
5115 gfc_copy_loopinfo_to_se (&rse, &loop);
5116
5117 lse.ss = loop.temp_ss;
5118 rse.ss = ss;
5119
5120 gfc_conv_scalarized_array_ref (&lse, NULL);
2b052ce2
PT
5121 if (expr->ts.type == BT_CHARACTER)
5122 {
5123 gfc_conv_expr (&rse, expr);
20b1cbc3
L
5124 if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
5125 rse.expr = build_fold_indirect_ref (rse.expr);
2b052ce2
PT
5126 }
5127 else
5128 gfc_conv_expr_val (&rse, expr);
6de9cd9a
DN
5129
5130 gfc_add_block_to_block (&block, &rse.pre);
5131 gfc_add_block_to_block (&block, &lse.pre);
5132
129c14bd
PT
5133 lse.string_length = rse.string_length;
5134 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
5135 expr->expr_type == EXPR_VARIABLE);
5136 gfc_add_expr_to_block (&block, tmp);
6de9cd9a
DN
5137
5138 /* Finish the copying loops. */
5139 gfc_trans_scalarizing_loops (&loop, &block);
5140
6de9cd9a 5141 desc = loop.temp_ss->data.info.descriptor;
6de9cd9a 5142
6e45f57b 5143 gcc_assert (is_gimple_lvalue (desc));
6de9cd9a 5144 }
fc90a8f2
PB
5145 else if (expr->expr_type == EXPR_FUNCTION)
5146 {
5147 desc = info->descriptor;
7823229b 5148 se->string_length = ss->string_length;
fc90a8f2 5149 }
6de9cd9a
DN
5150 else
5151 {
fc90a8f2
PB
5152 /* We pass sections without copying to a temporary. Make a new
5153 descriptor and point it at the section we want. The loop variable
5154 limits will be the limits of the section.
5155 A function may decide to repack the array to speed up access, but
5156 we're not bothered about that here. */
114e4d10 5157 int dim, ndim;
6de9cd9a
DN
5158 tree parm;
5159 tree parmtype;
5160 tree stride;
5161 tree from;
5162 tree to;
5163 tree base;
5164
fc90a8f2 5165 /* Set the string_length for a character array. */
20c9dc8a 5166 if (expr->ts.type == BT_CHARACTER)
ca2940c3 5167 se->string_length = gfc_get_expr_charlen (expr);
20c9dc8a 5168
6de9cd9a 5169 desc = info->descriptor;
6e45f57b 5170 gcc_assert (secss && secss != gfc_ss_terminator);
6de9cd9a
DN
5171 if (se->direct_byref)
5172 {
5173 /* For pointer assignments we fill in the destination. */
5174 parm = se->expr;
5175 parmtype = TREE_TYPE (parm);
5176 }
5177 else
5178 {
5179 /* Otherwise make a new one. */
5180 parmtype = gfc_get_element_type (TREE_TYPE (desc));
5181 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
fad0afd7
JJ
5182 loop.from, loop.to, 0,
5183 GFC_ARRAY_UNKNOWN);
6de9cd9a
DN
5184 parm = gfc_create_var (parmtype, "parm");
5185 }
5186
7ab92584 5187 offset = gfc_index_zero_node;
6de9cd9a
DN
5188 dim = 0;
5189
5190 /* The following can be somewhat confusing. We have two
5191 descriptors, a new one and the original array.
5192 {parm, parmtype, dim} refer to the new one.
5193 {desc, type, n, secss, loop} refer to the original, which maybe
5194 a descriptorless array.
e7dc5b4f 5195 The bounds of the scalarization are the bounds of the section.
6de9cd9a
DN
5196 We don't have to worry about numeric overflows when calculating
5197 the offsets because all elements are within the array data. */
5198
5199 /* Set the dtype. */
5200 tmp = gfc_conv_descriptor_dtype (parm);
726a989a 5201 gfc_add_modify (&loop.pre, tmp, gfc_get_dtype (parmtype));
6de9cd9a 5202
a7d318ea
TB
5203 /* Set offset for assignments to pointer only to zero if it is not
5204 the full array. */
5205 if (se->direct_byref
5206 && info->ref && info->ref->u.ar.type != AR_FULL)
7ab92584 5207 base = gfc_index_zero_node;
c4ba8848
PT
5208 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5209 base = gfc_evaluate_now (gfc_conv_array_offset (desc), &loop.pre);
6de9cd9a
DN
5210 else
5211 base = NULL_TREE;
5212
114e4d10
RS
5213 ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
5214 for (n = 0; n < ndim; n++)
6de9cd9a
DN
5215 {
5216 stride = gfc_conv_array_stride (desc, n);
5217
5218 /* Work out the offset. */
114e4d10
RS
5219 if (info->ref
5220 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6de9cd9a 5221 {
6e45f57b 5222 gcc_assert (info->subscript[n]
6de9cd9a
DN
5223 && info->subscript[n]->type == GFC_SS_SCALAR);
5224 start = info->subscript[n]->data.scalar.expr;
5225 }
5226 else
5227 {
5228 /* Check we haven't somehow got out of sync. */
6e45f57b 5229 gcc_assert (info->dim[dim] == n);
6de9cd9a
DN
5230
5231 /* Evaluate and remember the start of the section. */
5232 start = info->start[dim];
5233 stride = gfc_evaluate_now (stride, &loop.pre);
5234 }
5235
5236 tmp = gfc_conv_array_lbound (desc, n);
10c7a96f 5237 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp);
6de9cd9a 5238
10c7a96f
SB
5239 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride);
5240 offset = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp);
6de9cd9a 5241
114e4d10
RS
5242 if (info->ref
5243 && info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
6de9cd9a
DN
5244 {
5245 /* For elemental dimensions, we only need the offset. */
5246 continue;
5247 }
5248
5249 /* Vector subscripts need copying and are handled elsewhere. */
114e4d10
RS
5250 if (info->ref)
5251 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
6de9cd9a
DN
5252
5253 /* Set the new lower bound. */
5254 from = loop.from[dim];
5255 to = loop.to[dim];
4fd9a813 5256
a7d318ea
TB
5257 /* If we have an array section or are assigning make sure that
5258 the lower bound is 1. References to the full
4fd9a813 5259 array should otherwise keep the original bounds. */
114e4d10 5260 if ((!info->ref
a7d318ea 5261 || info->ref->u.ar.type != AR_FULL)
4fd9a813 5262 && !integer_onep (from))
6de9cd9a 5263 {
10c7a96f
SB
5264 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
5265 gfc_index_one_node, from);
5266 to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
7ab92584 5267 from = gfc_index_one_node;
6de9cd9a
DN
5268 }
5269 tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
726a989a 5270 gfc_add_modify (&loop.pre, tmp, from);
6de9cd9a
DN
5271
5272 /* Set the new upper bound. */
5273 tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
726a989a 5274 gfc_add_modify (&loop.pre, tmp, to);
6de9cd9a
DN
5275
5276 /* Multiply the stride by the section stride to get the
5277 total stride. */
10c7a96f
SB
5278 stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
5279 stride, info->stride[dim]);
6de9cd9a 5280
a7d318ea 5281 if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
c4ba8848
PT
5282 {
5283 base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
5284 base, stride);
5285 }
5286 else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5287 {
5288 tmp = gfc_conv_array_lbound (desc, n);
5289 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
5290 tmp, loop.from[dim]);
5291 tmp = fold_build2 (MULT_EXPR, TREE_TYPE (base),
5292 tmp, gfc_conv_array_stride (desc, n));
5293 base = fold_build2 (PLUS_EXPR, TREE_TYPE (base),
5294 tmp, base);
5295 }
6de9cd9a
DN
5296
5297 /* Store the new stride. */
5298 tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
726a989a 5299 gfc_add_modify (&loop.pre, tmp, stride);
6de9cd9a
DN
5300
5301 dim++;
5302 }
5303
ad5dd90d
PT
5304 if (se->data_not_needed)
5305 gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
5306 else
1d6b7f39
PT
5307 /* Point the data pointer at the first element in the section. */
5308 gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
5309 subref_array_target, expr);
6de9cd9a 5310
c4ba8848 5311 if ((se->direct_byref || GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
a7d318ea 5312 && !se->data_not_needed)
6de9cd9a
DN
5313 {
5314 /* Set the offset. */
5315 tmp = gfc_conv_descriptor_offset (parm);
726a989a 5316 gfc_add_modify (&loop.pre, tmp, base);
6de9cd9a
DN
5317 }
5318 else
5319 {
5320 /* Only the callee knows what the correct offset it, so just set
5321 it to zero here. */
5322 tmp = gfc_conv_descriptor_offset (parm);
726a989a 5323 gfc_add_modify (&loop.pre, tmp, gfc_index_zero_node);
6de9cd9a 5324 }
7a70c12d
RS
5325 desc = parm;
5326 }
6de9cd9a 5327
7a70c12d
RS
5328 if (!se->direct_byref)
5329 {
5330 /* Get a pointer to the new descriptor. */
5331 if (se->want_pointer)
628c189e 5332 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
7a70c12d
RS
5333 else
5334 se->expr = desc;
6de9cd9a
DN
5335 }
5336
5337 gfc_add_block_to_block (&se->pre, &loop.pre);
5338 gfc_add_block_to_block (&se->post, &loop.post);
5339
5340 /* Cleanup the scalarizer. */
5341 gfc_cleanup_loop (&loop);
5342}
5343
7e279142
JJ
5344/* Helper function for gfc_conv_array_parameter if array size needs to be
5345 computed. */
5346
5347static void
5348array_parameter_size (tree desc, gfc_expr *expr, tree *size)
5349{
5350 tree elem;
5351 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
5352 *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
5353 else if (expr->rank > 1)
5354 *size = build_call_expr (gfor_fndecl_size0, 1,
5355 gfc_build_addr_expr (NULL, desc));
5356 else
5357 {
5358 tree ubound = gfc_conv_descriptor_ubound (desc, gfc_index_zero_node);
5359 tree lbound = gfc_conv_descriptor_lbound (desc, gfc_index_zero_node);
5360
5361 *size = fold_build2 (MINUS_EXPR, gfc_array_index_type, ubound, lbound);
5362 *size = fold_build2 (PLUS_EXPR, gfc_array_index_type, *size,
5363 gfc_index_one_node);
5364 *size = fold_build2 (MAX_EXPR, gfc_array_index_type, *size,
5365 gfc_index_zero_node);
5366 }
5367 elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
5368 *size = fold_build2 (MULT_EXPR, gfc_array_index_type, *size,
5369 fold_convert (gfc_array_index_type, elem));
5370}
6de9cd9a
DN
5371
5372/* Convert an array for passing as an actual parameter. */
5373/* TODO: Optimize passing g77 arrays. */
5374
5375void
0d52899f 5376gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
7e279142
JJ
5377 const gfc_symbol *fsym, const char *proc_name,
5378 tree *size)
6de9cd9a
DN
5379{
5380 tree ptr;
5381 tree desc;
bd075cf2 5382 tree tmp = NULL_TREE;
6de9cd9a 5383 tree stmt;
b2b247f9
PT
5384 tree parent = DECL_CONTEXT (current_function_decl);
5385 bool full_array_var, this_array_result;
6de9cd9a
DN
5386 gfc_symbol *sym;
5387 stmtblock_t block;
5388
b2b247f9 5389 full_array_var = (expr->expr_type == EXPR_VARIABLE
71690b03
EB
5390 && expr->ref->type == REF_ARRAY
5391 && expr->ref->u.ar.type == AR_FULL);
b2b247f9
PT
5392 sym = full_array_var ? expr->symtree->n.sym : NULL;
5393
18b0679f
DK
5394 /* The symbol should have an array specification. */
5395 gcc_assert (!sym || sym->as);
5396
0ee8e250
PT
5397 if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
5398 {
5399 get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
83dffdeb 5400 expr->ts.cl->backend_decl = tmp;
f2d3cb25 5401 se->string_length = tmp;
0ee8e250
PT
5402 }
5403
b2b247f9
PT
5404 /* Is this the result of the enclosing procedure? */
5405 this_array_result = (full_array_var && sym->attr.flavor == FL_PROCEDURE);
5406 if (this_array_result
5407 && (sym->backend_decl != current_function_decl)
5408 && (sym->backend_decl != parent))
5409 this_array_result = false;
5410
6de9cd9a 5411 /* Passing address of the array if it is not pointer or assumed-shape. */
b2b247f9 5412 if (full_array_var && g77 && !this_array_result)
6de9cd9a 5413 {
b122dc6a 5414 tmp = gfc_get_symbol_decl (sym);
83d890b9 5415
20c9dc8a
TS
5416 if (sym->ts.type == BT_CHARACTER)
5417 se->string_length = sym->ts.cl->backend_decl;
6de9cd9a
DN
5418 if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE
5419 && !sym->attr.allocatable)
5420 {
346d5977 5421 /* Some variables are declared directly, others are declared as
841b0c1f
PB
5422 pointers and allocated on the heap. */
5423 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
5424 se->expr = tmp;
6de9cd9a 5425 else
628c189e 5426 se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
7e279142
JJ
5427 if (size)
5428 array_parameter_size (tmp, expr, size);
6de9cd9a
DN
5429 return;
5430 }
5431 if (sym->attr.allocatable)
5432 {
237b2f1b 5433 if (sym->attr.dummy || sym->attr.result)
7f0d6da9
EE
5434 {
5435 gfc_conv_expr_descriptor (se, expr, ss);
7e279142 5436 tmp = se->expr;
7f0d6da9 5437 }
7e279142
JJ
5438 if (size)
5439 array_parameter_size (tmp, expr, size);
5440 se->expr = gfc_conv_array_data (tmp);
6de9cd9a
DN
5441 return;
5442 }
5443 }
5444
b2b247f9
PT
5445 if (this_array_result)
5446 {
5447 /* Result of the enclosing function. */
5448 gfc_conv_expr_descriptor (se, expr, ss);
7e279142
JJ
5449 if (size)
5450 array_parameter_size (se->expr, expr, size);
628c189e 5451 se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
b2b247f9
PT
5452
5453 if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
5454 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
5455 se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
5456
5457 return;
5458 }
5459 else
5460 {
5461 /* Every other type of array. */
5462 se->want_pointer = 1;
5463 gfc_conv_expr_descriptor (se, expr, ss);
7e279142
JJ
5464 if (size)
5465 array_parameter_size (build_fold_indirect_ref (se->expr),
5466 expr, size);
b2b247f9
PT
5467 }
5468
5046aff5
PT
5469 /* Deallocate the allocatable components of structures that are
5470 not variable. */
5471 if (expr->ts.type == BT_DERIVED
5472 && expr->ts.derived->attr.alloc_comp
5473 && expr->expr_type != EXPR_VARIABLE)
5474 {
5475 tmp = build_fold_indirect_ref (se->expr);
5476 tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
5477 gfc_add_expr_to_block (&se->post, tmp);
5478 }
5479
6de9cd9a
DN
5480 if (g77)
5481 {
5482 desc = se->expr;
5483 /* Repack the array. */
bdfd2ff0
TK
5484
5485 if (gfc_option.warn_array_temp)
0d52899f
TB
5486 {
5487 if (fsym)
5488 gfc_warning ("Creating array temporary at %L for argument '%s'",
5489 &expr->where, fsym->name);
5490 else
5491 gfc_warning ("Creating array temporary at %L", &expr->where);
5492 }
bdfd2ff0 5493
5039610b 5494 ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
0d52899f
TB
5495
5496 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
5497 {
5498 tmp = gfc_conv_expr_present (sym);
6e1b67b3
RG
5499 ptr = build3 (COND_EXPR, TREE_TYPE (se->expr), tmp,
5500 fold_convert (TREE_TYPE (se->expr), ptr),
5501 fold_convert (TREE_TYPE (se->expr), null_pointer_node));
0d52899f
TB
5502 }
5503
6de9cd9a 5504 ptr = gfc_evaluate_now (ptr, &se->pre);
0d52899f 5505
6de9cd9a
DN
5506 se->expr = ptr;
5507
d3d3011f 5508 if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
0d52899f
TB
5509 {
5510 char * msg;
5511
5512 if (fsym && proc_name)
5513 asprintf (&msg, "An array temporary was created for argument "
5514 "'%s' of procedure '%s'", fsym->name, proc_name);
5515 else
5516 asprintf (&msg, "An array temporary was created");
5517
5518 tmp = build_fold_indirect_ref (desc);
5519 tmp = gfc_conv_array_data (tmp);
5520 tmp = fold_build2 (NE_EXPR, boolean_type_node,
5521 fold_convert (TREE_TYPE (tmp), ptr), tmp);
5522
5523 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
5524 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
5525 gfc_conv_expr_present (sym), tmp);
5526
5527 gfc_trans_runtime_check (false, true, tmp, &se->pre,
5528 &expr->where, msg);
5529 gfc_free (msg);
5530 }
5531
6de9cd9a
DN
5532 gfc_start_block (&block);
5533
5534 /* Copy the data back. */
0d52899f
TB
5535 if (fsym == NULL || fsym->attr.intent != INTENT_IN)
5536 {
5537 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
5538 gfc_add_expr_to_block (&block, tmp);
5539 }
6de9cd9a
DN
5540
5541 /* Free the temporary. */
1529b8d9 5542 tmp = gfc_call_free (convert (pvoid_type_node, ptr));
6de9cd9a
DN
5543 gfc_add_expr_to_block (&block, tmp);
5544
5545 stmt = gfc_finish_block (&block);
5546
5547 gfc_init_block (&block);
5548 /* Only if it was repacked. This code needs to be executed before the
5549 loop cleanup code. */
38611275 5550 tmp = build_fold_indirect_ref (desc);
6de9cd9a 5551 tmp = gfc_conv_array_data (tmp);
44855d8c
TS
5552 tmp = fold_build2 (NE_EXPR, boolean_type_node,
5553 fold_convert (TREE_TYPE (tmp), ptr), tmp);
0d52899f
TB
5554
5555 if (fsym && fsym->attr.optional && sym && sym->attr.optional)
5556 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
5557 gfc_conv_expr_present (sym), tmp);
5558
923ab88c 5559 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a
DN
5560
5561 gfc_add_expr_to_block (&block, tmp);
5562 gfc_add_block_to_block (&block, &se->post);
5563
5564 gfc_init_block (&se->post);
5565 gfc_add_block_to_block (&se->post, &block);
5566 }
5567}
5568
5569
763ccd45 5570/* Generate code to deallocate an array, if it is allocated. */
42a0e16c
PT
5571
5572tree
763ccd45 5573gfc_trans_dealloc_allocated (tree descriptor)
42a0e16c
PT
5574{
5575 tree tmp;
5046aff5 5576 tree var;
42a0e16c
PT
5577 stmtblock_t block;
5578
42a0e16c 5579 gfc_start_block (&block);
42a0e16c 5580
54200abb
RG
5581 var = gfc_conv_descriptor_data_get (descriptor);
5582 STRIP_NOPS (var);
5046aff5 5583
4376b7cf 5584 /* Call array_deallocate with an int * present in the second argument.
5046aff5
PT
5585 Although it is ignored here, it's presence ensures that arrays that
5586 are already deallocated are ignored. */
f25a62a5 5587 tmp = gfc_deallocate_with_status (var, NULL_TREE, true, NULL);
42a0e16c 5588 gfc_add_expr_to_block (&block, tmp);
54200abb
RG
5589
5590 /* Zero the data pointer. */
44855d8c
TS
5591 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
5592 var, build_int_cst (TREE_TYPE (var), 0));
54200abb
RG
5593 gfc_add_expr_to_block (&block, tmp);
5594
5046aff5
PT
5595 return gfc_finish_block (&block);
5596}
5597
5598
5599/* This helper function calculates the size in words of a full array. */
5600
5601static tree
5602get_full_array_size (stmtblock_t *block, tree decl, int rank)
5603{
5604 tree idx;
5605 tree nelems;
5606 tree tmp;
5607 idx = gfc_rank_cst[rank - 1];
5608 nelems = gfc_conv_descriptor_ubound (decl, idx);
5609 tmp = gfc_conv_descriptor_lbound (decl, idx);
44855d8c
TS
5610 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
5611 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
5612 tmp, gfc_index_one_node);
5046aff5
PT
5613 tmp = gfc_evaluate_now (tmp, block);
5614
5615 nelems = gfc_conv_descriptor_stride (decl, idx);
44855d8c 5616 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
5046aff5
PT
5617 return gfc_evaluate_now (tmp, block);
5618}
42a0e16c 5619
5046aff5
PT
5620
5621/* Allocate dest to the same size as src, and copy src -> dest. */
5622
5623tree
5624gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
5625{
5626 tree tmp;
5627 tree size;
5628 tree nelems;
5046aff5
PT
5629 tree null_cond;
5630 tree null_data;
5631 stmtblock_t block;
5632
66e4ab31 5633 /* If the source is null, set the destination to null. */
5046aff5
PT
5634 gfc_init_block (&block);
5635 gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
5636 null_data = gfc_finish_block (&block);
5637
5638 gfc_init_block (&block);
5639
5640 nelems = get_full_array_size (&block, src, rank);
5641 size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
7c57b2f1
FXC
5642 fold_convert (gfc_array_index_type,
5643 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
5046aff5
PT
5644
5645 /* Allocate memory to the destination. */
1529b8d9
FXC
5646 tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
5647 size);
5046aff5
PT
5648 gfc_conv_descriptor_data_set (&block, dest, tmp);
5649
5650 /* We know the temporary and the value will be the same length,
5651 so can use memcpy. */
5046aff5 5652 tmp = built_in_decls[BUILT_IN_MEMCPY];
5039610b
SL
5653 tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
5654 gfc_conv_descriptor_data_get (src), size);
5046aff5 5655 gfc_add_expr_to_block (&block, tmp);
42a0e16c
PT
5656 tmp = gfc_finish_block (&block);
5657
5046aff5
PT
5658 /* Null the destination if the source is null; otherwise do
5659 the allocate and copy. */
5660 null_cond = gfc_conv_descriptor_data_get (src);
5661 null_cond = convert (pvoid_type_node, null_cond);
44855d8c
TS
5662 null_cond = fold_build2 (NE_EXPR, boolean_type_node,
5663 null_cond, null_pointer_node);
5046aff5
PT
5664 return build3_v (COND_EXPR, null_cond, tmp, null_data);
5665}
5666
5667
5668/* Recursively traverse an object of derived type, generating code to
5669 deallocate, nullify or copy allocatable components. This is the work horse
5670 function for the functions named in this enum. */
5671
5672enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
5673
5674static tree
5675structure_alloc_comps (gfc_symbol * der_type, tree decl,
5676 tree dest, int rank, int purpose)
5677{
5678 gfc_component *c;
5679 gfc_loopinfo loop;
5680 stmtblock_t fnblock;
5681 stmtblock_t loopbody;
5682 tree tmp;
5683 tree comp;
5684 tree dcmp;
5685 tree nelems;
5686 tree index;
5687 tree var;
5688 tree cdecl;
5689 tree ctype;
5690 tree vref, dref;
5691 tree null_cond = NULL_TREE;
5692
5693 gfc_init_block (&fnblock);
5694
7114edca
PT
5695 if (POINTER_TYPE_P (TREE_TYPE (decl)))
5696 decl = build_fold_indirect_ref (decl);
5697
5046aff5
PT
5698 /* If this an array of derived types with allocatable components
5699 build a loop and recursively call this function. */
5700 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
5701 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5702 {
5703 tmp = gfc_conv_array_data (decl);
5704 var = build_fold_indirect_ref (tmp);
5705
5706 /* Get the number of elements - 1 and set the counter. */
5707 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
5708 {
5709 /* Use the descriptor for an allocatable array. Since this
5710 is a full array reference, we only need the descriptor
5711 information from dimension = rank. */
5712 tmp = get_full_array_size (&fnblock, decl, rank);
44855d8c
TS
5713 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
5714 tmp, gfc_index_one_node);
5046aff5
PT
5715
5716 null_cond = gfc_conv_descriptor_data_get (decl);
44855d8c
TS
5717 null_cond = fold_build2 (NE_EXPR, boolean_type_node, null_cond,
5718 build_int_cst (TREE_TYPE (null_cond), 0));
5046aff5
PT
5719 }
5720 else
5721 {
5722 /* Otherwise use the TYPE_DOMAIN information. */
5723 tmp = array_type_nelts (TREE_TYPE (decl));
5724 tmp = fold_convert (gfc_array_index_type, tmp);
5725 }
5726
5727 /* Remember that this is, in fact, the no. of elements - 1. */
5728 nelems = gfc_evaluate_now (tmp, &fnblock);
5729 index = gfc_create_var (gfc_array_index_type, "S");
5730
5731 /* Build the body of the loop. */
5732 gfc_init_block (&loopbody);
5733
1d6b7f39 5734 vref = gfc_build_array_ref (var, index, NULL);
5046aff5
PT
5735
5736 if (purpose == COPY_ALLOC_COMP)
5737 {
b945f9f3
PT
5738 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (dest)))
5739 {
5740 tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
5741 gfc_add_expr_to_block (&fnblock, tmp);
5742 }
5743 tmp = build_fold_indirect_ref (gfc_conv_array_data (dest));
1d6b7f39 5744 dref = gfc_build_array_ref (tmp, index, NULL);
5046aff5
PT
5745 tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
5746 }
5747 else
5748 tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
5749
5750 gfc_add_expr_to_block (&loopbody, tmp);
5751
66e4ab31 5752 /* Build the loop and return. */
5046aff5
PT
5753 gfc_init_loopinfo (&loop);
5754 loop.dimen = 1;
5755 loop.from[0] = gfc_index_zero_node;
5756 loop.loopvar[0] = index;
5757 loop.to[0] = nelems;
5758 gfc_trans_scalarizing_loops (&loop, &loopbody);
5759 gfc_add_block_to_block (&fnblock, &loop.pre);
5760
5761 tmp = gfc_finish_block (&fnblock);
5762 if (null_cond != NULL_TREE)
5763 tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
5764
5765 return tmp;
5766 }
5767
5768 /* Otherwise, act on the components or recursively call self to
66e4ab31 5769 act on a chain of components. */
5046aff5
PT
5770 for (c = der_type->components; c; c = c->next)
5771 {
5772 bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
5773 && c->ts.derived->attr.alloc_comp;
5774 cdecl = c->backend_decl;
5775 ctype = TREE_TYPE (cdecl);
5776
5777 switch (purpose)
5778 {
5779 case DEALLOCATE_ALLOC_COMP:
5780 /* Do not deallocate the components of ultimate pointer
5781 components. */
d4b7d0f0 5782 if (cmp_has_alloc_comps && !c->attr.pointer)
5046aff5 5783 {
44855d8c
TS
5784 comp = fold_build3 (COMPONENT_REF, ctype,
5785 decl, cdecl, NULL_TREE);
5046aff5
PT
5786 rank = c->as ? c->as->rank : 0;
5787 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5788 rank, purpose);
5789 gfc_add_expr_to_block (&fnblock, tmp);
5790 }
5791
d4b7d0f0 5792 if (c->attr.allocatable)
5046aff5 5793 {
44855d8c
TS
5794 comp = fold_build3 (COMPONENT_REF, ctype,
5795 decl, cdecl, NULL_TREE);
5046aff5
PT
5796 tmp = gfc_trans_dealloc_allocated (comp);
5797 gfc_add_expr_to_block (&fnblock, tmp);
5798 }
5799 break;
5800
5801 case NULLIFY_ALLOC_COMP:
d4b7d0f0 5802 if (c->attr.pointer)
5046aff5 5803 continue;
d4b7d0f0 5804 else if (c->attr.allocatable)
5046aff5 5805 {
44855d8c
TS
5806 comp = fold_build3 (COMPONENT_REF, ctype,
5807 decl, cdecl, NULL_TREE);
5046aff5
PT
5808 gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
5809 }
5810 else if (cmp_has_alloc_comps)
5811 {
44855d8c
TS
5812 comp = fold_build3 (COMPONENT_REF, ctype,
5813 decl, cdecl, NULL_TREE);
5046aff5
PT
5814 rank = c->as ? c->as->rank : 0;
5815 tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
5816 rank, purpose);
5817 gfc_add_expr_to_block (&fnblock, tmp);
5818 }
5819 break;
5820
5821 case COPY_ALLOC_COMP:
d4b7d0f0 5822 if (c->attr.pointer)
5046aff5
PT
5823 continue;
5824
5825 /* We need source and destination components. */
44855d8c
TS
5826 comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
5827 dcmp = fold_build3 (COMPONENT_REF, ctype, dest, cdecl, NULL_TREE);
5046aff5
PT
5828 dcmp = fold_convert (TREE_TYPE (comp), dcmp);
5829
d4b7d0f0 5830 if (c->attr.allocatable && !cmp_has_alloc_comps)
5046aff5
PT
5831 {
5832 tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
5833 gfc_add_expr_to_block (&fnblock, tmp);
5834 }
5835
5836 if (cmp_has_alloc_comps)
5837 {
5838 rank = c->as ? c->as->rank : 0;
5839 tmp = fold_convert (TREE_TYPE (dcmp), comp);
726a989a 5840 gfc_add_modify (&fnblock, dcmp, tmp);
5046aff5
PT
5841 tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
5842 rank, purpose);
5843 gfc_add_expr_to_block (&fnblock, tmp);
5844 }
5845 break;
5846
5847 default:
5848 gcc_unreachable ();
5849 break;
5850 }
5851 }
5852
5853 return gfc_finish_block (&fnblock);
5854}
5855
5856/* Recursively traverse an object of derived type, generating code to
5857 nullify allocatable components. */
5858
5859tree
5860gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5861{
5862 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5863 NULLIFY_ALLOC_COMP);
42a0e16c
PT
5864}
5865
5866
5046aff5
PT
5867/* Recursively traverse an object of derived type, generating code to
5868 deallocate allocatable components. */
5869
5870tree
5871gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
5872{
5873 return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
5874 DEALLOCATE_ALLOC_COMP);
5875}
5876
5877
5878/* Recursively traverse an object of derived type, generating code to
5879 copy its allocatable components. */
5880
5881tree
5882gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
5883{
5884 return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP);
5885}
5886
5887
5888/* NULLIFY an allocatable/pointer array on function entry, free it on exit.
5889 Do likewise, recursively if necessary, with the allocatable components of
5890 derived types. */
6de9cd9a
DN
5891
5892tree
5893gfc_trans_deferred_array (gfc_symbol * sym, tree body)
5894{
5895 tree type;
5896 tree tmp;
5897 tree descriptor;
6de9cd9a
DN
5898 stmtblock_t fnblock;
5899 locus loc;
5046aff5
PT
5900 int rank;
5901 bool sym_has_alloc_comp;
5902
5903 sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
5904 && sym->ts.derived->attr.alloc_comp;
6de9cd9a
DN
5905
5906 /* Make sure the frontend gets these right. */
5046aff5
PT
5907 if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
5908 fatal_error ("Possible frontend bug: Deferred array size without pointer, "
5909 "allocatable attribute or derived type without allocatable "
5910 "components.");
6de9cd9a
DN
5911
5912 gfc_init_block (&fnblock);
5913
99c7ab42 5914 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
5046aff5 5915 || TREE_CODE (sym->backend_decl) == PARM_DECL);
99c7ab42 5916
6de9cd9a
DN
5917 if (sym->ts.type == BT_CHARACTER
5918 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
417ab240 5919 {
4b7f8314 5920 gfc_conv_string_length (sym->ts.cl, NULL, &fnblock);
417ab240
JJ
5921 gfc_trans_vla_type_sizes (sym, &fnblock);
5922 }
6de9cd9a 5923
bafc96b4
PT
5924 /* Dummy, use associated and result variables don't need anything special. */
5925 if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
6de9cd9a
DN
5926 {
5927 gfc_add_expr_to_block (&fnblock, body);
5928
5929 return gfc_finish_block (&fnblock);
5930 }
5931
5932 gfc_get_backend_locus (&loc);
5933 gfc_set_backend_locus (&sym->declared_at);
5934 descriptor = sym->backend_decl;
5935
b2a43373 5936 /* Although static, derived types with default initializers and
5046aff5
PT
5937 allocatable components must not be nulled wholesale; instead they
5938 are treated component by component. */
5939 if (TREE_STATIC (descriptor) && !sym_has_alloc_comp)
6de9cd9a
DN
5940 {
5941 /* SAVEd variables are not freed on exit. */
5942 gfc_trans_static_array_pointer (sym);
5943 return body;
5944 }
5945
5946 /* Get the descriptor type. */
5947 type = TREE_TYPE (sym->backend_decl);
5046aff5
PT
5948
5949 if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
5950 {
36d3fb4c
PT
5951 if (!sym->attr.save)
5952 {
5953 rank = sym->as ? sym->as->rank : 0;
5954 tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
5955 gfc_add_expr_to_block (&fnblock, tmp);
f40eccb0
PT
5956 if (sym->value)
5957 {
5958 tmp = gfc_init_default_dt (sym, NULL);
5959 gfc_add_expr_to_block (&fnblock, tmp);
5960 }
36d3fb4c 5961 }
5046aff5
PT
5962 }
5963 else if (!GFC_DESCRIPTOR_TYPE_P (type))
f5f701ad
PT
5964 {
5965 /* If the backend_decl is not a descriptor, we must have a pointer
5966 to one. */
5967 descriptor = build_fold_indirect_ref (sym->backend_decl);
5968 type = TREE_TYPE (descriptor);
f5f701ad 5969 }
5046aff5 5970
6de9cd9a 5971 /* NULLIFY the data pointer. */
3672065a 5972 if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
5046aff5 5973 gfc_conv_descriptor_data_set (&fnblock, descriptor, null_pointer_node);
6de9cd9a
DN
5974
5975 gfc_add_expr_to_block (&fnblock, body);
5976
5977 gfc_set_backend_locus (&loc);
5046aff5
PT
5978
5979 /* Allocatable arrays need to be freed when they go out of scope.
5980 The allocatable components of pointers must not be touched. */
5981 if (sym_has_alloc_comp && !(sym->attr.function || sym->attr.result)
36d3fb4c 5982 && !sym->attr.pointer && !sym->attr.save)
5046aff5
PT
5983 {
5984 int rank;
5985 rank = sym->as ? sym->as->rank : 0;
5986 tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
5987 gfc_add_expr_to_block (&fnblock, tmp);
5988 }
5989
a9b98c2c 5990 if (sym->attr.allocatable && !sym->attr.save && !sym->attr.result)
6de9cd9a 5991 {
763ccd45 5992 tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
6de9cd9a
DN
5993 gfc_add_expr_to_block (&fnblock, tmp);
5994 }
5995
5996 return gfc_finish_block (&fnblock);
5997}
5998
5999/************ Expression Walking Functions ******************/
6000
6001/* Walk a variable reference.
6002
6003 Possible extension - multiple component subscripts.
6004 x(:,:) = foo%a(:)%b(:)
6005 Transforms to
6006 forall (i=..., j=...)
6007 x(i,j) = foo%a(j)%b(i)
6008 end forall
735dfed7 6009 This adds a fair amount of complexity because you need to deal with more
6de9cd9a
DN
6010 than one ref. Maybe handle in a similar manner to vector subscripts.
6011 Maybe not worth the effort. */
6012
6013
6014static gfc_ss *
6015gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
6016{
6017 gfc_ref *ref;
6018 gfc_array_ref *ar;
6019 gfc_ss *newss;
6020 gfc_ss *head;
6021 int n;
6022
6023 for (ref = expr->ref; ref; ref = ref->next)
068e7338
RS
6024 if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
6025 break;
6026
6027 for (; ref; ref = ref->next)
6de9cd9a 6028 {
068e7338
RS
6029 if (ref->type == REF_SUBSTRING)
6030 {
6031 newss = gfc_get_ss ();
6032 newss->type = GFC_SS_SCALAR;
6033 newss->expr = ref->u.ss.start;
6034 newss->next = ss;
6035 ss = newss;
6036
6037 newss = gfc_get_ss ();
6038 newss->type = GFC_SS_SCALAR;
6039 newss->expr = ref->u.ss.end;
6040 newss->next = ss;
6041 ss = newss;
6042 }
6043
6044 /* We're only interested in array sections from now on. */
6de9cd9a
DN
6045 if (ref->type != REF_ARRAY)
6046 continue;
6047
6048 ar = &ref->u.ar;
6049 switch (ar->type)
6050 {
6051 case AR_ELEMENT:
068e7338
RS
6052 for (n = 0; n < ar->dimen; n++)
6053 {
6054 newss = gfc_get_ss ();
6055 newss->type = GFC_SS_SCALAR;
6056 newss->expr = ar->start[n];
6057 newss->next = ss;
6058 ss = newss;
6059 }
6de9cd9a
DN
6060 break;
6061
6062 case AR_FULL:
6063 newss = gfc_get_ss ();
6064 newss->type = GFC_SS_SECTION;
6065 newss->expr = expr;
6066 newss->next = ss;
6067 newss->data.info.dimen = ar->as->rank;
6068 newss->data.info.ref = ref;
6069
6070 /* Make sure array is the same as array(:,:), this way
6071 we don't need to special case all the time. */
6072 ar->dimen = ar->as->rank;
6073 for (n = 0; n < ar->dimen; n++)
6074 {
6075 newss->data.info.dim[n] = n;
6076 ar->dimen_type[n] = DIMEN_RANGE;
6077
6e45f57b
PB
6078 gcc_assert (ar->start[n] == NULL);
6079 gcc_assert (ar->end[n] == NULL);
6080 gcc_assert (ar->stride[n] == NULL);
6de9cd9a 6081 }
068e7338
RS
6082 ss = newss;
6083 break;
6de9cd9a
DN
6084
6085 case AR_SECTION:
6086 newss = gfc_get_ss ();
6087 newss->type = GFC_SS_SECTION;
6088 newss->expr = expr;
6089 newss->next = ss;
6090 newss->data.info.dimen = 0;
6091 newss->data.info.ref = ref;
6092
6093 head = newss;
6094
6095 /* We add SS chains for all the subscripts in the section. */
6096 for (n = 0; n < ar->dimen; n++)
6097 {
6098 gfc_ss *indexss;
6099
6100 switch (ar->dimen_type[n])
6101 {
6102 case DIMEN_ELEMENT:
6103 /* Add SS for elemental (scalar) subscripts. */
6e45f57b 6104 gcc_assert (ar->start[n]);
6de9cd9a
DN
6105 indexss = gfc_get_ss ();
6106 indexss->type = GFC_SS_SCALAR;
6107 indexss->expr = ar->start[n];
6108 indexss->next = gfc_ss_terminator;
6109 indexss->loop_chain = gfc_ss_terminator;
6110 newss->data.info.subscript[n] = indexss;
6111 break;
6112
6113 case DIMEN_RANGE:
6114 /* We don't add anything for sections, just remember this
6115 dimension for later. */
6116 newss->data.info.dim[newss->data.info.dimen] = n;
6117 newss->data.info.dimen++;
6118 break;
6119
6120 case DIMEN_VECTOR:
7a70c12d
RS
6121 /* Create a GFC_SS_VECTOR index in which we can store
6122 the vector's descriptor. */
6123 indexss = gfc_get_ss ();
6de9cd9a 6124 indexss->type = GFC_SS_VECTOR;
7a70c12d
RS
6125 indexss->expr = ar->start[n];
6126 indexss->next = gfc_ss_terminator;
6127 indexss->loop_chain = gfc_ss_terminator;
6de9cd9a 6128 newss->data.info.subscript[n] = indexss;
6de9cd9a
DN
6129 newss->data.info.dim[newss->data.info.dimen] = n;
6130 newss->data.info.dimen++;
6131 break;
6132
6133 default:
6134 /* We should know what sort of section it is by now. */
6e45f57b 6135 gcc_unreachable ();
6de9cd9a
DN
6136 }
6137 }
6138 /* We should have at least one non-elemental dimension. */
6e45f57b 6139 gcc_assert (newss->data.info.dimen > 0);
068e7338 6140 ss = newss;
6de9cd9a
DN
6141 break;
6142
6143 default:
6144 /* We should know what sort of section it is by now. */
6e45f57b 6145 gcc_unreachable ();
6de9cd9a
DN
6146 }
6147
6148 }
6149 return ss;
6150}
6151
6152
6153/* Walk an expression operator. If only one operand of a binary expression is
6154 scalar, we must also add the scalar term to the SS chain. */
6155
6156static gfc_ss *
6157gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
6158{
6159 gfc_ss *head;
6160 gfc_ss *head2;
6161 gfc_ss *newss;
6162
58b03ab2
TS
6163 head = gfc_walk_subexpr (ss, expr->value.op.op1);
6164 if (expr->value.op.op2 == NULL)
6de9cd9a
DN
6165 head2 = head;
6166 else
58b03ab2 6167 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
6de9cd9a
DN
6168
6169 /* All operands are scalar. Pass back and let the caller deal with it. */
6170 if (head2 == ss)
6171 return head2;
6172
f7b529fa 6173 /* All operands require scalarization. */
58b03ab2 6174 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
6de9cd9a
DN
6175 return head2;
6176
6177 /* One of the operands needs scalarization, the other is scalar.
6178 Create a gfc_ss for the scalar expression. */
6179 newss = gfc_get_ss ();
6180 newss->type = GFC_SS_SCALAR;
6181 if (head == ss)
6182 {
6183 /* First operand is scalar. We build the chain in reverse order, so
df2fba9e 6184 add the scalar SS after the second operand. */
6de9cd9a
DN
6185 head = head2;
6186 while (head && head->next != ss)
6187 head = head->next;
6188 /* Check we haven't somehow broken the chain. */
6e45f57b 6189 gcc_assert (head);
6de9cd9a
DN
6190 newss->next = ss;
6191 head->next = newss;
58b03ab2 6192 newss->expr = expr->value.op.op1;
6de9cd9a
DN
6193 }
6194 else /* head2 == head */
6195 {
6e45f57b 6196 gcc_assert (head2 == head);
6de9cd9a
DN
6197 /* Second operand is scalar. */
6198 newss->next = head2;
6199 head2 = newss;
58b03ab2 6200 newss->expr = expr->value.op.op2;
6de9cd9a
DN
6201 }
6202
6203 return head2;
6204}
6205
6206
6207/* Reverse a SS chain. */
6208
48474141 6209gfc_ss *
6de9cd9a
DN
6210gfc_reverse_ss (gfc_ss * ss)
6211{
6212 gfc_ss *next;
6213 gfc_ss *head;
6214
6e45f57b 6215 gcc_assert (ss != NULL);
6de9cd9a
DN
6216
6217 head = gfc_ss_terminator;
6218 while (ss != gfc_ss_terminator)
6219 {
6220 next = ss->next;
6e45f57b
PB
6221 /* Check we didn't somehow break the chain. */
6222 gcc_assert (next != NULL);
6de9cd9a
DN
6223 ss->next = head;
6224 head = ss;
6225 ss = next;
6226 }
6227
6228 return (head);
6229}
6230
6231
6232/* Walk the arguments of an elemental function. */
6233
6234gfc_ss *
48474141 6235gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
6de9cd9a
DN
6236 gfc_ss_type type)
6237{
6de9cd9a
DN
6238 int scalar;
6239 gfc_ss *head;
6240 gfc_ss *tail;
6241 gfc_ss *newss;
6242
6243 head = gfc_ss_terminator;
6244 tail = NULL;
6245 scalar = 1;
48474141 6246 for (; arg; arg = arg->next)
6de9cd9a
DN
6247 {
6248 if (!arg->expr)
6249 continue;
6250
6251 newss = gfc_walk_subexpr (head, arg->expr);
6252 if (newss == head)
6253 {
1f2959f0 6254 /* Scalar argument. */
6de9cd9a
DN
6255 newss = gfc_get_ss ();
6256 newss->type = type;
6257 newss->expr = arg->expr;
6258 newss->next = head;
6259 }
6260 else
6261 scalar = 0;
6262
6263 head = newss;
6264 if (!tail)
6265 {
6266 tail = head;
6267 while (tail->next != gfc_ss_terminator)
6268 tail = tail->next;
6269 }
6270 }
6271
6272 if (scalar)
6273 {
6274 /* If all the arguments are scalar we don't need the argument SS. */
6275 gfc_free_ss_chain (head);
6276 /* Pass it back. */
6277 return ss;
6278 }
6279
6280 /* Add it onto the existing chain. */
6281 tail->next = ss;
6282 return head;
6283}
6284
6285
6286/* Walk a function call. Scalar functions are passed back, and taken out of
6287 scalarization loops. For elemental functions we walk their arguments.
6288 The result of functions returning arrays is stored in a temporary outside
6289 the loop, so that the function is only called once. Hence we do not need
6290 to walk their arguments. */
6291
6292static gfc_ss *
6293gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
6294{
6295 gfc_ss *newss;
6296 gfc_intrinsic_sym *isym;
6297 gfc_symbol *sym;
6298
6299 isym = expr->value.function.isym;
6300
13413760 6301 /* Handle intrinsic functions separately. */
6de9cd9a
DN
6302 if (isym)
6303 return gfc_walk_intrinsic_function (ss, expr, isym);
6304
6305 sym = expr->value.function.esym;
6306 if (!sym)
6307 sym = expr->symtree->n.sym;
6308
6309 /* A function that returns arrays. */
6310 if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
6311 {
6312 newss = gfc_get_ss ();
6313 newss->type = GFC_SS_FUNCTION;
6314 newss->expr = expr;
6315 newss->next = ss;
6316 newss->data.info.dimen = expr->rank;
6317 return newss;
6318 }
6319
6320 /* Walk the parameters of an elemental function. For now we always pass
6321 by reference. */
6322 if (sym->attr.elemental)
48474141
PT
6323 return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
6324 GFC_SS_REFERENCE);
6de9cd9a 6325
e7dc5b4f 6326 /* Scalar functions are OK as these are evaluated outside the scalarization
6de9cd9a
DN
6327 loop. Pass back and let the caller deal with it. */
6328 return ss;
6329}
6330
6331
6332/* An array temporary is constructed for array constructors. */
6333
6334static gfc_ss *
6335gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
6336{
6337 gfc_ss *newss;
6338 int n;
6339
6340 newss = gfc_get_ss ();
6341 newss->type = GFC_SS_CONSTRUCTOR;
6342 newss->expr = expr;
6343 newss->next = ss;
6344 newss->data.info.dimen = expr->rank;
6345 for (n = 0; n < expr->rank; n++)
6346 newss->data.info.dim[n] = n;
6347
6348 return newss;
6349}
6350
6351
1f2959f0 6352/* Walk an expression. Add walked expressions to the head of the SS chain.
aa9c57ec 6353 A wholly scalar expression will not be added. */
6de9cd9a
DN
6354
6355static gfc_ss *
6356gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
6357{
6358 gfc_ss *head;
6359
6360 switch (expr->expr_type)
6361 {
6362 case EXPR_VARIABLE:
6363 head = gfc_walk_variable_expr (ss, expr);
6364 return head;
6365
6366 case EXPR_OP:
6367 head = gfc_walk_op_expr (ss, expr);
6368 return head;
6369
6370 case EXPR_FUNCTION:
6371 head = gfc_walk_function_expr (ss, expr);
6372 return head;
6373
6374 case EXPR_CONSTANT:
6375 case EXPR_NULL:
6376 case EXPR_STRUCTURE:
6377 /* Pass back and let the caller deal with it. */
6378 break;
6379
6380 case EXPR_ARRAY:
6381 head = gfc_walk_array_constructor (ss, expr);
6382 return head;
6383
6384 case EXPR_SUBSTRING:
6385 /* Pass back and let the caller deal with it. */
6386 break;
6387
6388 default:
6389 internal_error ("bad expression type during walk (%d)",
6390 expr->expr_type);
6391 }
6392 return ss;
6393}
6394
6395
6396/* Entry point for expression walking.
6397 A return value equal to the passed chain means this is
6398 a scalar expression. It is up to the caller to take whatever action is
1f2959f0 6399 necessary to translate these. */
6de9cd9a
DN
6400
6401gfc_ss *
6402gfc_walk_expr (gfc_expr * expr)
6403{
6404 gfc_ss *res;
6405
6406 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
6407 return gfc_reverse_ss (res);
6408}