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