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