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