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