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