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