]> gcc.gnu.org Git - gcc.git/blame - gcc/fortran/trans-array.c
Unrevert previously reversed patch, adding this patch:
[gcc.git] / gcc / fortran / trans-array.c
CommitLineData
6de9cd9a 1/* Array translation routines
ec378180 2 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
6de9cd9a
DN
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
5
9fc4d79b 6This file is part of GCC.
6de9cd9a 7
9fc4d79b
TS
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
6de9cd9a 12
9fc4d79b
TS
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
6de9cd9a
DN
17
18You should have received a copy of the GNU General Public License
9fc4d79b
TS
19along with GCC; see the file COPYING. If not, write to the Free
20Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2102111-1307, USA. */
6de9cd9a
DN
22
23/* trans-array.c-- Various array related code, including scalarization,
24 allocation, initialization and other support routines. */
25
26/* How the scalarizer works.
27 In gfortran, array expressions use the same core routines as scalar
28 expressions.
29 First, a Scalarization State (SS) chain is built. This is done by walking
30 the expression tree, and building a linear list of the terms in the
31 expression. As the tree is walked, scalar subexpressions are translated.
32
33 The scalarization parameters are stored in a gfc_loopinfo structure.
34 First the start and stride of each term is calculated by
35 gfc_conv_ss_startstride. During this process the expressions for the array
36 descriptors and data pointers are also translated.
37
38 If the expression is an assignment, we must then resolve any dependencies.
39 In fortran all the rhs values of an assignment must be evaluated before
40 any assignments take place. This can require a temporary array to store the
41 values. We also require a temporary when we are passing array expressions
42 or vector subecripts as procedure parameters.
43
44 Array sections are passed without copying to a temporary. These use the
45 scalarizer to determine the shape of the section. The flag
46 loop->array_parameter tells the scalarizer that the actual values and loop
47 variables will not be required.
48
49 The function gfc_conv_loop_setup generates the scalarization setup code.
50 It determines the range of the scalarizing loop variables. If a temporary
51 is required, this is created and initialized. Code for scalar expressions
52 taken outside the loop is also generated at this time. Next the offset and
53 scaling required to translate from loop variables to array indices for each
54 term is calculated.
55
56 A call to gfc_start_scalarized_body marks the start of the scalarized
57 expression. This creates a scope and declares the loop variables. Before
58 calling this gfc_make_ss_chain_used must be used to indicate which terms
59 will be used inside this loop.
60
61 The scalar gfc_conv_* functions are then used to build the main body of the
62 scalarization loop. Scalarization loop variables and precalculated scalar
1f2959f0 63 values are automatically substituted. Note that gfc_advance_se_ss_chain
6de9cd9a
DN
64 must be used, rather than changing the se->ss directly.
65
66 For assignment expressions requiring a temporary two sub loops are
67 generated. The first stores the result of the expression in the temporary,
68 the second copies it to the result. A call to
69 gfc_trans_scalarized_loop_boundary marks the end of the main loop code and
70 the start of the copying loop. The temporary may be less than full rank.
71
72 Finally gfc_trans_scalarizing_loops is called to generate the implicit do
73 loops. The loops are added to the pre chain of the loopinfo. The post
74 chain may still contain cleanup code.
75
76 After the loop code has been added into its parent scope gfc_cleanup_loop
77 is called to free all the SS allocated by the scalarizer. */
78
79#include "config.h"
80#include "system.h"
81#include "coretypes.h"
82#include "tree.h"
eadf906f 83#include "tree-gimple.h"
6de9cd9a
DN
84#include "ggc.h"
85#include "toplev.h"
86#include "real.h"
87#include "flags.h"
6de9cd9a
DN
88#include "gfortran.h"
89#include "trans.h"
90#include "trans-stmt.h"
91#include "trans-types.h"
92#include "trans-array.h"
93#include "trans-const.h"
94#include "dependency.h"
95
96static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
97
13413760 98/* The contents of this structure aren't actually used, just the address. */
6de9cd9a
DN
99static gfc_ss gfc_ss_terminator_var;
100gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;
101
102unsigned HOST_WIDE_INT gfc_stack_space_left;
103
104
105/* Returns true if a variable of specified size should go on the stack. */
106
107int
108gfc_can_put_var_on_stack (tree size)
109{
110 unsigned HOST_WIDE_INT low;
111
112 if (!INTEGER_CST_P (size))
113 return 0;
114
115 if (gfc_option.flag_max_stack_var_size < 0)
116 return 1;
117
118 if (TREE_INT_CST_HIGH (size) != 0)
119 return 0;
120
121 low = TREE_INT_CST_LOW (size);
122 if (low > (unsigned HOST_WIDE_INT) gfc_option.flag_max_stack_var_size)
123 return 0;
124
125/* TODO: Set a per-function stack size limit. */
126#if 0
127 /* We should be a bit more clever with array temps. */
128 if (gfc_option.flag_max_function_vars_size >= 0)
129 {
130 if (low > gfc_stack_space_left)
131 return 0;
132
133 gfc_stack_space_left -= low;
134 }
135#endif
136
137 return 1;
138}
139
140static tree
141gfc_array_dataptr_type (tree desc)
142{
143 return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
144}
145
146
147/* Build expressions to access the members of an array descriptor.
148 It's surprisingly easy to mess up here, so never access
149 an array descriptor by "brute force", always use these
150 functions. This also avoids problems if we change the format
151 of an array descriptor.
152
153 To understand these magic numbers, look at the comments
154 before gfc_build_array_type() in trans-types.c.
155
156 The code within these defines should be the only code which knows the format
157 of an array descriptor.
158
159 Any code just needing to read obtain the bounds of an array should use
160 gfc_conv_array_* rather than the following functions as these will return
161 know constant values, and work with arrays which do not have descriptors.
162
163 Don't forget to #undef these! */
164
165#define DATA_FIELD 0
166#define OFFSET_FIELD 1
167#define DTYPE_FIELD 2
168#define DIMENSION_FIELD 3
169
170#define STRIDE_SUBFIELD 0
171#define LBOUND_SUBFIELD 1
172#define UBOUND_SUBFIELD 2
173
174tree
175gfc_conv_descriptor_data (tree desc)
176{
177 tree field;
178 tree type;
179
180 type = TREE_TYPE (desc);
6e45f57b 181 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
182
183 field = TYPE_FIELDS (type);
6e45f57b
PB
184 gcc_assert (DATA_FIELD == 0);
185 gcc_assert (field != NULL_TREE
6de9cd9a
DN
186 && TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
187 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == ARRAY_TYPE);
188
923ab88c 189 return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
6de9cd9a
DN
190}
191
192tree
193gfc_conv_descriptor_offset (tree desc)
194{
195 tree type;
196 tree field;
197
198 type = TREE_TYPE (desc);
6e45f57b 199 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
200
201 field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);
6e45f57b 202 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 203
923ab88c 204 return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
6de9cd9a
DN
205}
206
207tree
208gfc_conv_descriptor_dtype (tree desc)
209{
210 tree field;
211 tree type;
212
213 type = TREE_TYPE (desc);
6e45f57b 214 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
215
216 field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
6e45f57b 217 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 218
923ab88c 219 return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
6de9cd9a
DN
220}
221
222static tree
223gfc_conv_descriptor_dimension (tree desc, tree dim)
224{
225 tree field;
226 tree type;
227 tree tmp;
228
229 type = TREE_TYPE (desc);
6e45f57b 230 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
231
232 field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
6e45f57b 233 gcc_assert (field != NULL_TREE
6de9cd9a
DN
234 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
235 && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
236
923ab88c 237 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);
6de9cd9a
DN
238 tmp = gfc_build_array_ref (tmp, dim);
239 return tmp;
240}
241
242tree
243gfc_conv_descriptor_stride (tree desc, tree dim)
244{
245 tree tmp;
246 tree field;
247
248 tmp = gfc_conv_descriptor_dimension (desc, dim);
249 field = TYPE_FIELDS (TREE_TYPE (tmp));
250 field = gfc_advance_chain (field, STRIDE_SUBFIELD);
6e45f57b 251 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 252
923ab88c 253 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
6de9cd9a
DN
254 return tmp;
255}
256
257tree
258gfc_conv_descriptor_lbound (tree desc, tree dim)
259{
260 tree tmp;
261 tree field;
262
263 tmp = gfc_conv_descriptor_dimension (desc, dim);
264 field = TYPE_FIELDS (TREE_TYPE (tmp));
265 field = gfc_advance_chain (field, LBOUND_SUBFIELD);
6e45f57b 266 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 267
923ab88c 268 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
6de9cd9a
DN
269 return tmp;
270}
271
272tree
273gfc_conv_descriptor_ubound (tree desc, tree dim)
274{
275 tree tmp;
276 tree field;
277
278 tmp = gfc_conv_descriptor_dimension (desc, dim);
279 field = TYPE_FIELDS (TREE_TYPE (tmp));
280 field = gfc_advance_chain (field, UBOUND_SUBFIELD);
6e45f57b 281 gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);
6de9cd9a 282
923ab88c 283 tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);
6de9cd9a
DN
284 return tmp;
285}
286
287
331c72f3 288/* Build an null array descriptor constructor. */
6de9cd9a 289
331c72f3
PB
290tree
291gfc_build_null_descriptor (tree type)
6de9cd9a 292{
6de9cd9a 293 tree field;
331c72f3 294 tree tmp;
6de9cd9a 295
6e45f57b
PB
296 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
297 gcc_assert (DATA_FIELD == 0);
6de9cd9a
DN
298 field = TYPE_FIELDS (type);
299
331c72f3 300 /* Set a NULL data pointer. */
6de9cd9a
DN
301 tmp = tree_cons (field, null_pointer_node, NULL_TREE);
302 tmp = build1 (CONSTRUCTOR, type, tmp);
303 TREE_CONSTANT (tmp) = 1;
304 TREE_INVARIANT (tmp) = 1;
331c72f3
PB
305 /* All other fields are ignored. */
306
307 return tmp;
6de9cd9a
DN
308}
309
310
311/* Cleanup those #defines. */
312
313#undef DATA_FIELD
314#undef OFFSET_FIELD
315#undef DTYPE_FIELD
316#undef DIMENSION_FIELD
317#undef STRIDE_SUBFIELD
318#undef LBOUND_SUBFIELD
319#undef UBOUND_SUBFIELD
320
321
322/* Mark a SS chain as used. Flags specifies in which loops the SS is used.
323 flags & 1 = Main loop body.
324 flags & 2 = temp copy loop. */
325
326void
327gfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags)
328{
329 for (; ss != gfc_ss_terminator; ss = ss->next)
330 ss->useflags = flags;
331}
332
333static void gfc_free_ss (gfc_ss *);
334
335
336/* Free a gfc_ss chain. */
337
338static void
339gfc_free_ss_chain (gfc_ss * ss)
340{
341 gfc_ss *next;
342
343 while (ss != gfc_ss_terminator)
344 {
6e45f57b 345 gcc_assert (ss != NULL);
6de9cd9a
DN
346 next = ss->next;
347 gfc_free_ss (ss);
348 ss = next;
349 }
350}
351
352
353/* Free a SS. */
354
355static void
356gfc_free_ss (gfc_ss * ss)
357{
358 int n;
359
360 switch (ss->type)
361 {
362 case GFC_SS_SECTION:
363 case GFC_SS_VECTOR:
364 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
365 {
366 if (ss->data.info.subscript[n])
367 gfc_free_ss_chain (ss->data.info.subscript[n]);
368 }
369 break;
370
371 default:
372 break;
373 }
374
375 gfc_free (ss);
376}
377
378
379/* Free all the SS associated with a loop. */
380
381void
382gfc_cleanup_loop (gfc_loopinfo * loop)
383{
384 gfc_ss *ss;
385 gfc_ss *next;
386
387 ss = loop->ss;
388 while (ss != gfc_ss_terminator)
389 {
6e45f57b 390 gcc_assert (ss != NULL);
6de9cd9a
DN
391 next = ss->loop_chain;
392 gfc_free_ss (ss);
393 ss = next;
394 }
395}
396
397
398/* Associate a SS chain with a loop. */
399
400void
401gfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head)
402{
403 gfc_ss *ss;
404
405 if (head == gfc_ss_terminator)
406 return;
407
408 ss = head;
409 for (; ss && ss != gfc_ss_terminator; ss = ss->next)
410 {
411 if (ss->next == gfc_ss_terminator)
412 ss->loop_chain = loop->ss;
413 else
414 ss->loop_chain = ss->next;
415 }
6e45f57b 416 gcc_assert (ss == gfc_ss_terminator);
6de9cd9a
DN
417 loop->ss = head;
418}
419
420
331c72f3
PB
421/* Generate an initializer for a static pointer or allocatable array. */
422
423void
424gfc_trans_static_array_pointer (gfc_symbol * sym)
425{
426 tree type;
427
6e45f57b 428 gcc_assert (TREE_STATIC (sym->backend_decl));
331c72f3
PB
429 /* Just zero the data member. */
430 type = TREE_TYPE (sym->backend_decl);
431 DECL_INITIAL (sym->backend_decl) =gfc_build_null_descriptor (type);
432}
433
434
6de9cd9a 435/* Generate code to allocate an array temporary, or create a variable to
fc90a8f2
PB
436 hold the data. If size is NULL zero the descriptor so that so that the
437 callee will allocate the array. Also generates code to free the array
438 afterwards. */
6de9cd9a
DN
439
440static void
441gfc_trans_allocate_array_storage (gfc_loopinfo * loop, gfc_ss_info * info,
442 tree size, tree nelem)
443{
444 tree tmp;
445 tree args;
446 tree desc;
447 tree data;
448 bool onstack;
449
450 desc = info->descriptor;
451 data = gfc_conv_descriptor_data (desc);
fc90a8f2 452 if (size == NULL_TREE)
6de9cd9a 453 {
fc90a8f2
PB
454 /* A callee allocated array. */
455 gfc_add_modify_expr (&loop->pre, data, convert (TREE_TYPE (data),
456 gfc_index_zero_node));
6de9cd9a
DN
457 info->data = data;
458 info->offset = gfc_index_zero_node;
fc90a8f2 459 onstack = FALSE;
6de9cd9a
DN
460 }
461 else
462 {
fc90a8f2
PB
463 /* Allocate the temporary. */
464 onstack = gfc_can_put_var_on_stack (size);
465
466 if (onstack)
467 {
468 /* Make a temporary variable to hold the data. */
923ab88c
TS
469 tmp = fold (build2 (MINUS_EXPR, TREE_TYPE (nelem), nelem,
470 integer_one_node));
fc90a8f2
PB
471 tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
472 tmp);
473 tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
474 tmp);
475 tmp = gfc_create_var (tmp, "A");
476 tmp = gfc_build_addr_expr (TREE_TYPE (data), tmp);
477 gfc_add_modify_expr (&loop->pre, data, tmp);
478 info->data = data;
479 info->offset = gfc_index_zero_node;
6de9cd9a 480
fc90a8f2 481 }
6de9cd9a 482 else
fc90a8f2
PB
483 {
484 /* Allocate memory to hold the data. */
485 args = gfc_chainon_list (NULL_TREE, size);
6de9cd9a 486
fc90a8f2
PB
487 if (gfc_index_integer_kind == 4)
488 tmp = gfor_fndecl_internal_malloc;
489 else if (gfc_index_integer_kind == 8)
490 tmp = gfor_fndecl_internal_malloc64;
491 else
6e45f57b 492 gcc_unreachable ();
fc90a8f2
PB
493 tmp = gfc_build_function_call (tmp, args);
494 tmp = convert (TREE_TYPE (data), tmp);
495 gfc_add_modify_expr (&loop->pre, data, tmp);
496
497 info->data = data;
498 info->offset = gfc_index_zero_node;
499 }
6de9cd9a
DN
500 }
501
502 /* The offset is zero because we create temporaries with a zero
503 lower bound. */
504 tmp = gfc_conv_descriptor_offset (desc);
505 gfc_add_modify_expr (&loop->pre, tmp, gfc_index_zero_node);
506
507 if (!onstack)
508 {
509 /* Free the temporary. */
510 tmp = convert (pvoid_type_node, info->data);
511 tmp = gfc_chainon_list (NULL_TREE, tmp);
512 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
513 gfc_add_expr_to_block (&loop->post, tmp);
514 }
515}
516
517
518/* Generate code to allocate and initialize the descriptor for a temporary
e7dc5b4f 519 array. This is used for both temporaries needed by the scalarizer, and
fc90a8f2
PB
520 functions returning arrays. Adjusts the loop variables to be zero-based,
521 and calculates the loop bounds for callee allocated arrays.
522 Also fills in the descriptor, data and offset fields of info if known.
523 Returns the size of the array, or NULL for a callee allocated array. */
6de9cd9a
DN
524
525tree
526gfc_trans_allocate_temp_array (gfc_loopinfo * loop, gfc_ss_info * info,
40f20186 527 tree eltype)
6de9cd9a
DN
528{
529 tree type;
530 tree desc;
531 tree tmp;
532 tree size;
533 tree nelem;
534 int n;
535 int dim;
536
6e45f57b 537 gcc_assert (info->dimen > 0);
6de9cd9a
DN
538 /* Set the lower bound to zero. */
539 for (dim = 0; dim < info->dimen; dim++)
540 {
541 n = loop->order[dim];
542 if (n < loop->temp_dim)
6e45f57b 543 gcc_assert (integer_zerop (loop->from[n]));
6de9cd9a
DN
544 else
545 {
fc90a8f2
PB
546 /* Callee allocated arrays may not have a known bound yet. */
547 if (loop->to[n])
923ab88c
TS
548 loop->to[n] = fold (build2 (MINUS_EXPR, gfc_array_index_type,
549 loop->to[n], loop->from[n]));
7ab92584 550 loop->from[n] = gfc_index_zero_node;
6de9cd9a
DN
551 }
552
7ab92584
SB
553 info->delta[dim] = gfc_index_zero_node;
554 info->start[dim] = gfc_index_zero_node;
555 info->stride[dim] = gfc_index_one_node;
6de9cd9a
DN
556 info->dim[dim] = dim;
557 }
558
13413760 559 /* Initialize the descriptor. */
6de9cd9a
DN
560 type =
561 gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1);
562 desc = gfc_create_var (type, "atmp");
563 GFC_DECL_PACKED_ARRAY (desc) = 1;
564
565 info->descriptor = desc;
7ab92584 566 size = gfc_index_one_node;
6de9cd9a
DN
567
568 /* Fill in the array dtype. */
569 tmp = gfc_conv_descriptor_dtype (desc);
40b026d8 570 gfc_add_modify_expr (&loop->pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
6de9cd9a 571
7ab92584
SB
572 /*
573 Fill in the bounds and stride. This is a packed array, so:
574
6de9cd9a
DN
575 size = 1;
576 for (n = 0; n < rank; n++)
7ab92584
SB
577 {
578 stride[n] = size
579 delta = ubound[n] + 1 - lbound[n];
580 size = size * delta;
581 }
582 size = size * sizeof(element);
583 */
584
6de9cd9a
DN
585 for (n = 0; n < info->dimen; n++)
586 {
fc90a8f2
PB
587 if (loop->to[n] == NULL_TREE)
588 {
589 /* For a callee allocated array express the loop bounds in terms
590 of the descriptor fields. */
923ab88c
TS
591 tmp = build2 (MINUS_EXPR, gfc_array_index_type,
592 gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
593 gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
fc90a8f2
PB
594 loop->to[n] = tmp;
595 size = NULL_TREE;
596 continue;
597 }
598
6de9cd9a
DN
599 /* Store the stride and bound components in the descriptor. */
600 tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
601 gfc_add_modify_expr (&loop->pre, tmp, size);
602
603 tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
7ab92584 604 gfc_add_modify_expr (&loop->pre, tmp, gfc_index_zero_node);
6de9cd9a
DN
605
606 tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
607 gfc_add_modify_expr (&loop->pre, tmp, loop->to[n]);
608
923ab88c
TS
609 tmp = fold (build2 (PLUS_EXPR, gfc_array_index_type,
610 loop->to[n], gfc_index_one_node));
6de9cd9a 611
923ab88c 612 size = fold (build2 (MULT_EXPR, gfc_array_index_type, size, tmp));
6de9cd9a
DN
613 size = gfc_evaluate_now (size, &loop->pre);
614 }
615
6de9cd9a
DN
616 /* Get the size of the array. */
617 nelem = size;
fc90a8f2 618 if (size)
923ab88c
TS
619 size = fold (build2 (MULT_EXPR, gfc_array_index_type, size,
620 TYPE_SIZE_UNIT (gfc_get_element_type (type))));
6de9cd9a
DN
621
622 gfc_trans_allocate_array_storage (loop, info, size, nelem);
623
624 if (info->dimen > loop->temp_dim)
625 loop->temp_dim = info->dimen;
626
627 return size;
628}
629
630
631/* Make sure offset is a variable. */
632
633static void
634gfc_put_offset_into_var (stmtblock_t * pblock, tree * poffset,
635 tree * offsetvar)
636{
637 /* We should have already created the offset variable. We cannot
13413760 638 create it here because we may be in an inner scope. */
6e45f57b 639 gcc_assert (*offsetvar != NULL_TREE);
6de9cd9a
DN
640 gfc_add_modify_expr (pblock, *offsetvar, *poffset);
641 *poffset = *offsetvar;
642 TREE_USED (*offsetvar) = 1;
643}
644
645
40f20186
PB
646/* Assign an element of an array constructor. */
647
648static void
649gfc_trans_array_ctor_element (stmtblock_t * pblock, tree pointer,
650 tree offset, gfc_se * se, gfc_expr * expr)
651{
652 tree tmp;
653 tree args;
654
655 gfc_conv_expr (se, expr);
656
657 /* Store the value. */
658 tmp = gfc_build_indirect_ref (pointer);
659 tmp = gfc_build_array_ref (tmp, offset);
660 if (expr->ts.type == BT_CHARACTER)
661 {
662 gfc_conv_string_parameter (se);
663 if (POINTER_TYPE_P (TREE_TYPE (tmp)))
664 {
665 /* The temporary is an array of pointers. */
666 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
667 gfc_add_modify_expr (&se->pre, tmp, se->expr);
668 }
669 else
670 {
671 /* The temporary is an array of string values. */
672 tmp = gfc_build_addr_expr (pchar_type_node, tmp);
673 /* We know the temporary and the value will be the same length,
674 so can use memcpy. */
675 args = gfc_chainon_list (NULL_TREE, tmp);
676 args = gfc_chainon_list (args, se->expr);
677 args = gfc_chainon_list (args, se->string_length);
678 tmp = built_in_decls[BUILT_IN_MEMCPY];
679 tmp = gfc_build_function_call (tmp, args);
680 gfc_add_expr_to_block (&se->pre, tmp);
681 }
682 }
683 else
684 {
685 /* TODO: Should the frontend already have done this conversion? */
686 se->expr = fold_convert (TREE_TYPE (tmp), se->expr);
687 gfc_add_modify_expr (&se->pre, tmp, se->expr);
688 }
689
690 gfc_add_block_to_block (pblock, &se->pre);
691 gfc_add_block_to_block (pblock, &se->post);
692}
693
694
6de9cd9a
DN
695/* Add the contents of an array to the constructor. */
696
697static void
698gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
699 tree type ATTRIBUTE_UNUSED,
700 tree pointer, gfc_expr * expr,
701 tree * poffset, tree * offsetvar)
702{
703 gfc_se se;
704 gfc_ss *ss;
705 gfc_loopinfo loop;
706 stmtblock_t body;
707 tree tmp;
708
709 /* We need this to be a variable so we can increment it. */
710 gfc_put_offset_into_var (pblock, poffset, offsetvar);
711
712 gfc_init_se (&se, NULL);
713
714 /* Walk the array expression. */
715 ss = gfc_walk_expr (expr);
6e45f57b 716 gcc_assert (ss != gfc_ss_terminator);
6de9cd9a
DN
717
718 /* Initialize the scalarizer. */
719 gfc_init_loopinfo (&loop);
720 gfc_add_ss_to_loop (&loop, ss);
721
722 /* Initialize the loop. */
723 gfc_conv_ss_startstride (&loop);
724 gfc_conv_loop_setup (&loop);
725
726 /* Make the loop body. */
727 gfc_mark_ss_chain_used (ss, 1);
728 gfc_start_scalarized_body (&loop, &body);
729 gfc_copy_loopinfo_to_se (&se, &loop);
730 se.ss = ss;
731
40f20186
PB
732 if (expr->ts.type == BT_CHARACTER)
733 gfc_todo_error ("character arrays in constructors");
6de9cd9a 734
40f20186 735 gfc_trans_array_ctor_element (&body, pointer, *poffset, &se, expr);
6e45f57b 736 gcc_assert (se.ss == gfc_ss_terminator);
6de9cd9a
DN
737
738 /* Increment the offset. */
923ab88c 739 tmp = build2 (PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node);
6de9cd9a
DN
740 gfc_add_modify_expr (&body, *poffset, tmp);
741
742 /* Finish the loop. */
6de9cd9a
DN
743 gfc_trans_scalarizing_loops (&loop, &body);
744 gfc_add_block_to_block (&loop.pre, &loop.post);
745 tmp = gfc_finish_block (&loop.pre);
746 gfc_add_expr_to_block (pblock, tmp);
747
748 gfc_cleanup_loop (&loop);
749}
750
751
752/* Assign the values to the elements of an array constructor. */
753
754static void
755gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
756 tree pointer, gfc_constructor * c,
757 tree * poffset, tree * offsetvar)
758{
759 tree tmp;
6de9cd9a
DN
760 stmtblock_t body;
761 tree loopbody;
762 gfc_se se;
763
764 for (; c; c = c->next)
765 {
766 /* If this is an iterator or an array, the offset must be a variable. */
767 if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
768 gfc_put_offset_into_var (pblock, poffset, offsetvar);
769
770 gfc_start_block (&body);
771
772 if (c->expr->expr_type == EXPR_ARRAY)
773 {
774 /* Array constructors can be nested. */
775 gfc_trans_array_constructor_value (&body, type, pointer,
776 c->expr->value.constructor,
777 poffset, offsetvar);
778 }
779 else if (c->expr->rank > 0)
780 {
781 gfc_trans_array_constructor_subarray (&body, type, pointer,
782 c->expr, poffset, offsetvar);
783 }
784 else
785 {
786 /* This code really upsets the gimplifier so don't bother for now. */
787 gfc_constructor *p;
788 HOST_WIDE_INT n;
789 HOST_WIDE_INT size;
790
791 p = c;
792 n = 0;
793 while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
794 {
795 p = p->next;
796 n++;
797 }
798 if (n < 4)
799 {
800 /* Scalar values. */
801 gfc_init_se (&se, NULL);
40f20186
PB
802 gfc_trans_array_ctor_element (&body, pointer, *poffset, &se,
803 c->expr);
6de9cd9a 804
923ab88c
TS
805 *poffset = fold (build2 (PLUS_EXPR, gfc_array_index_type,
806 *poffset, gfc_index_one_node));
6de9cd9a
DN
807 }
808 else
809 {
810 /* Collect multiple scalar constants into a constructor. */
811 tree list;
812 tree init;
813 tree bound;
814 tree tmptype;
815
816 p = c;
817 list = NULL_TREE;
818 /* Count the number of consecutive scalar constants. */
819 while (p && !(p->iterator
820 || p->expr->expr_type != EXPR_CONSTANT))
821 {
822 gfc_init_se (&se, NULL);
823 gfc_conv_constant (&se, p->expr);
40f20186
PB
824 if (p->expr->ts.type == BT_CHARACTER
825 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE
826 (TREE_TYPE (pointer)))))
827 {
828 /* For constant character array constructors we build
829 an array of pointers. */
830 se.expr = gfc_build_addr_expr (pchar_type_node,
831 se.expr);
832 }
833
6de9cd9a
DN
834 list = tree_cons (NULL_TREE, se.expr, list);
835 c = p;
836 p = p->next;
837 }
838
7d60be94 839 bound = build_int_cst (NULL_TREE, n - 1);
6de9cd9a
DN
840 /* Create an array type to hold them. */
841 tmptype = build_range_type (gfc_array_index_type,
7ab92584 842 gfc_index_zero_node, bound);
6de9cd9a
DN
843 tmptype = build_array_type (type, tmptype);
844
845 init = build1 (CONSTRUCTOR, tmptype, nreverse (list));
846 TREE_CONSTANT (init) = 1;
847 TREE_INVARIANT (init) = 1;
848 TREE_STATIC (init) = 1;
849 /* Create a static variable to hold the data. */
850 tmp = gfc_create_var (tmptype, "data");
851 TREE_STATIC (tmp) = 1;
852 TREE_CONSTANT (tmp) = 1;
853 TREE_INVARIANT (tmp) = 1;
854 DECL_INITIAL (tmp) = init;
855 init = tmp;
856
857 /* Use BUILTIN_MEMCPY to assign the values. */
858 tmp = gfc_build_indirect_ref (pointer);
859 tmp = gfc_build_array_ref (tmp, *poffset);
860 tmp = gfc_build_addr_expr (NULL, tmp);
861 init = gfc_build_addr_expr (NULL, init);
862
863 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
7d60be94 864 bound = build_int_cst (NULL_TREE, n * size);
6de9cd9a
DN
865 tmp = gfc_chainon_list (NULL_TREE, tmp);
866 tmp = gfc_chainon_list (tmp, init);
867 tmp = gfc_chainon_list (tmp, bound);
868 tmp = gfc_build_function_call (built_in_decls[BUILT_IN_MEMCPY],
869 tmp);
870 gfc_add_expr_to_block (&body, tmp);
871
923ab88c
TS
872 *poffset = fold (build2 (PLUS_EXPR, gfc_array_index_type,
873 *poffset, bound));
6de9cd9a
DN
874 }
875 if (!INTEGER_CST_P (*poffset))
876 {
877 gfc_add_modify_expr (&body, *offsetvar, *poffset);
878 *poffset = *offsetvar;
879 }
880 }
881
882 /* The frontend should already have done any expansions. */
883 if (c->iterator)
884 {
885 tree end;
886 tree step;
887 tree loopvar;
888 tree exit_label;
889
890 loopbody = gfc_finish_block (&body);
891
892 gfc_init_se (&se, NULL);
893 gfc_conv_expr (&se, c->iterator->var);
894 gfc_add_block_to_block (pblock, &se.pre);
895 loopvar = se.expr;
896
13413760 897 /* Initialize the loop. */
6de9cd9a
DN
898 gfc_init_se (&se, NULL);
899 gfc_conv_expr_val (&se, c->iterator->start);
900 gfc_add_block_to_block (pblock, &se.pre);
901 gfc_add_modify_expr (pblock, loopvar, se.expr);
902
903 gfc_init_se (&se, NULL);
904 gfc_conv_expr_val (&se, c->iterator->end);
905 gfc_add_block_to_block (pblock, &se.pre);
906 end = gfc_evaluate_now (se.expr, pblock);
907
908 gfc_init_se (&se, NULL);
909 gfc_conv_expr_val (&se, c->iterator->step);
910 gfc_add_block_to_block (pblock, &se.pre);
911 step = gfc_evaluate_now (se.expr, pblock);
912
913 /* Generate the loop body. */
914 exit_label = gfc_build_label_decl (NULL_TREE);
915 gfc_start_block (&body);
916
917 /* Generate the exit condition. */
923ab88c 918 end = build2 (GT_EXPR, boolean_type_node, loopvar, end);
6de9cd9a
DN
919 tmp = build1_v (GOTO_EXPR, exit_label);
920 TREE_USED (exit_label) = 1;
923ab88c 921 tmp = build3_v (COND_EXPR, end, tmp, build_empty_stmt ());
6de9cd9a
DN
922 gfc_add_expr_to_block (&body, tmp);
923
924 /* The main loop body. */
925 gfc_add_expr_to_block (&body, loopbody);
926
927 /* Increment the loop variable. */
923ab88c 928 tmp = build2 (PLUS_EXPR, TREE_TYPE (loopvar), loopvar, step);
6de9cd9a
DN
929 gfc_add_modify_expr (&body, loopvar, tmp);
930
931 /* Finish the loop. */
932 tmp = gfc_finish_block (&body);
923ab88c 933 tmp = build1_v (LOOP_EXPR, tmp);
6de9cd9a
DN
934 gfc_add_expr_to_block (pblock, tmp);
935
936 /* Add the exit label. */
937 tmp = build1_v (LABEL_EXPR, exit_label);
938 gfc_add_expr_to_block (pblock, tmp);
939 }
940 else
941 {
942 /* Pass the code as is. */
943 tmp = gfc_finish_block (&body);
944 gfc_add_expr_to_block (pblock, tmp);
945 }
946 }
947}
948
949
950/* Get the size of an expression. Returns -1 if the size isn't constant.
951 Implied do loops with non-constant bounds are tricky because we must only
952 evaluate the bounds once. */
953
954static void
955gfc_get_array_cons_size (mpz_t * size, gfc_constructor * c)
956{
957 gfc_iterator *i;
958 mpz_t val;
959 mpz_t len;
960
961 mpz_set_ui (*size, 0);
962 mpz_init (len);
963 mpz_init (val);
964
965 for (; c; c = c->next)
966 {
967 if (c->expr->expr_type == EXPR_ARRAY)
968 {
969 /* A nested array constructor. */
970 gfc_get_array_cons_size (&len, c->expr->value.constructor);
971 if (mpz_sgn (len) < 0)
972 {
973 mpz_set (*size, len);
974 mpz_clear (len);
975 mpz_clear (val);
976 return;
977 }
978 }
979 else
980 {
981 if (c->expr->rank > 0)
982 {
983 mpz_set_si (*size, -1);
984 mpz_clear (len);
985 mpz_clear (val);
986 return;
987 }
988 mpz_set_ui (len, 1);
989 }
990
991 if (c->iterator)
992 {
993 i = c->iterator;
994
995 if (i->start->expr_type != EXPR_CONSTANT
996 || i->end->expr_type != EXPR_CONSTANT
997 || i->step->expr_type != EXPR_CONSTANT)
998 {
999 mpz_set_si (*size, -1);
1000 mpz_clear (len);
1001 mpz_clear (val);
1002 return;
1003 }
1004
1005 mpz_add (val, i->end->value.integer, i->start->value.integer);
1006 mpz_tdiv_q (val, val, i->step->value.integer);
1007 mpz_add_ui (val, val, 1);
1008 mpz_mul (len, len, val);
1009 }
1010 mpz_add (*size, *size, len);
1011 }
1012 mpz_clear (len);
1013 mpz_clear (val);
1014}
1015
1016
40f20186
PB
1017/* Figure out the string length of a variable reference expression.
1018 Used by get_array_ctor_strlen. */
1019
1020static void
1021get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
1022{
1023 gfc_ref *ref;
1024 gfc_typespec *ts;
1025
1026 /* Don't bother if we already know the length is a constant. */
1027 if (*len && INTEGER_CST_P (*len))
1028 return;
1029
1030 ts = &expr->symtree->n.sym->ts;
1031 for (ref = expr->ref; ref; ref = ref->next)
1032 {
1033 switch (ref->type)
1034 {
1035 case REF_ARRAY:
1036 /* Array references don't change teh sting length. */
1037 break;
1038
1039 case COMPONENT_REF:
f7b529fa 1040 /* Use the length of the component. */
40f20186
PB
1041 ts = &ref->u.c.component->ts;
1042 break;
1043
1044 default:
1045 /* TODO: Substrings are tricky because we can't evaluate the
1046 expression more than once. For now we just give up, and hope
1047 we can figure it out elsewhere. */
1048 return;
1049 }
1050 }
1051
1052 *len = ts->cl->backend_decl;
1053}
1054
1055
1056/* Figure out the string length of a character array constructor.
1057 Returns TRUE if all elements are character constants. */
1058
1059static bool
1060get_array_ctor_strlen (gfc_constructor * c, tree * len)
1061{
1062 bool is_const;
1063
1064 is_const = TRUE;
1065 for (; c; c = c->next)
1066 {
1067 switch (c->expr->expr_type)
1068 {
1069 case EXPR_CONSTANT:
1070 if (!(*len && INTEGER_CST_P (*len)))
d7177ab2 1071 *len = build_int_cstu (gfc_charlen_type_node,
40f20186
PB
1072 c->expr->value.character.length);
1073 break;
1074
1075 case EXPR_ARRAY:
1076 if (!get_array_ctor_strlen (c->expr->value.constructor, len))
1077 is_const = FALSE;
1078 break;
1079
1080 case EXPR_VARIABLE:
1081 is_const = false;
1082 get_array_ctor_var_strlen (c->expr, len);
1083 break;
1084
1085 default:
1086 is_const = FALSE;
1087 /* TODO: For now we just ignore anything we don't know how to
1088 handle, and hope we can figure it out a different way. */
1089 break;
1090 }
1091 }
1092
1093 return is_const;
1094}
1095
1096
6de9cd9a
DN
1097/* Array constructors are handled by constructing a temporary, then using that
1098 within the scalarization loop. This is not optimal, but seems by far the
1099 simplest method. */
1100
1101static void
1102gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss)
1103{
1104 tree offset;
1105 tree offsetvar;
1106 tree desc;
1107 tree size;
1108 tree type;
40f20186 1109 bool const_string;
6de9cd9a 1110
6de9cd9a 1111 ss->data.info.dimen = loop->dimen;
40f20186
PB
1112
1113 if (ss->expr->ts.type == BT_CHARACTER)
1114 {
1115 const_string = get_array_ctor_strlen (ss->expr->value.constructor,
1116 &ss->string_length);
1117 if (!ss->string_length)
1118 gfc_todo_error ("complex character array constructors");
1119
1120 type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
1121 if (const_string)
1122 type = build_pointer_type (type);
1123 }
1124 else
1125 {
1126 const_string = TRUE;
1127 type = gfc_typenode_for_spec (&ss->expr->ts);
1128 }
1129
1130 size = gfc_trans_allocate_temp_array (loop, &ss->data.info, type);
6de9cd9a
DN
1131
1132 desc = ss->data.info.descriptor;
7ab92584 1133 offset = gfc_index_zero_node;
6de9cd9a
DN
1134 offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
1135 TREE_USED (offsetvar) = 0;
1136 gfc_trans_array_constructor_value (&loop->pre, type,
1137 ss->data.info.data,
1138 ss->expr->value.constructor, &offset,
1139 &offsetvar);
1140
1141 if (TREE_USED (offsetvar))
1142 pushdecl (offsetvar);
1143 else
6e45f57b 1144 gcc_assert (INTEGER_CST_P (offset));
6de9cd9a 1145#if 0
dfc46c1f 1146 /* Disable bound checking for now because it's probably broken. */
6de9cd9a
DN
1147 if (flag_bounds_check)
1148 {
6e45f57b 1149 gcc_unreachable ();
6de9cd9a
DN
1150 }
1151#endif
1152}
1153
1154
1155/* Add the pre and post chains for all the scalar expressions in a SS chain
1156 to loop. This is called after the loop parameters have been calculated,
1157 but before the actual scalarizing loops. */
6de9cd9a
DN
1158
1159static void
1160gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript)
1161{
1162 gfc_se se;
1163 int n;
1164
e9cfef64
PB
1165 /* TODO: This can generate bad code if there are ordering dependencies.
1166 eg. a callee allocated function and an unknown size constructor. */
6e45f57b 1167 gcc_assert (ss != NULL);
6de9cd9a
DN
1168
1169 for (; ss != gfc_ss_terminator; ss = ss->loop_chain)
1170 {
6e45f57b 1171 gcc_assert (ss);
6de9cd9a
DN
1172
1173 switch (ss->type)
1174 {
1175 case GFC_SS_SCALAR:
1176 /* Scalar expression. Evaluate this now. This includes elemental
1177 dimension indices, but not array section bounds. */
1178 gfc_init_se (&se, NULL);
1179 gfc_conv_expr (&se, ss->expr);
1180 gfc_add_block_to_block (&loop->pre, &se.pre);
1181
1182 if (ss->expr->ts.type != BT_CHARACTER)
1183 {
1184 /* Move the evaluation of scalar expressions outside the
1185 scalarization loop. */
1186 if (subscript)
1187 se.expr = convert(gfc_array_index_type, se.expr);
1188 se.expr = gfc_evaluate_now (se.expr, &loop->pre);
1189 gfc_add_block_to_block (&loop->pre, &se.post);
1190 }
1191 else
1192 gfc_add_block_to_block (&loop->post, &se.post);
1193
1194 ss->data.scalar.expr = se.expr;
40f20186 1195 ss->string_length = se.string_length;
6de9cd9a
DN
1196 break;
1197
1198 case GFC_SS_REFERENCE:
1199 /* Scalar reference. Evaluate this now. */
1200 gfc_init_se (&se, NULL);
1201 gfc_conv_expr_reference (&se, ss->expr);
1202 gfc_add_block_to_block (&loop->pre, &se.pre);
1203 gfc_add_block_to_block (&loop->post, &se.post);
1204
1205 ss->data.scalar.expr = gfc_evaluate_now (se.expr, &loop->pre);
40f20186 1206 ss->string_length = se.string_length;
6de9cd9a
DN
1207 break;
1208
1209 case GFC_SS_SECTION:
1210 case GFC_SS_VECTOR:
1211 /* Scalarized expression. Evaluate any scalar subscripts. */
1212 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1213 {
1214 /* Add the expressions for scalar subscripts. */
1215 if (ss->data.info.subscript[n])
1216 gfc_add_loop_ss_code (loop, ss->data.info.subscript[n], true);
1217 }
1218 break;
1219
1220 case GFC_SS_INTRINSIC:
1221 gfc_add_intrinsic_ss_code (loop, ss);
1222 break;
1223
1224 case GFC_SS_FUNCTION:
1225 /* Array function return value. We call the function and save its
1226 result in a temporary for use inside the loop. */
1227 gfc_init_se (&se, NULL);
1228 se.loop = loop;
1229 se.ss = ss;
1230 gfc_conv_expr (&se, ss->expr);
1231 gfc_add_block_to_block (&loop->pre, &se.pre);
1232 gfc_add_block_to_block (&loop->post, &se.post);
1233 break;
1234
1235 case GFC_SS_CONSTRUCTOR:
1236 gfc_trans_array_constructor (loop, ss);
1237 break;
1238
fc90a8f2 1239 case GFC_SS_TEMP:
e9cfef64
PB
1240 case GFC_SS_COMPONENT:
1241 /* Do nothing. These are handled elsewhere. */
fc90a8f2
PB
1242 break;
1243
6de9cd9a 1244 default:
6e45f57b 1245 gcc_unreachable ();
6de9cd9a
DN
1246 }
1247 }
1248}
1249
1250
1251/* Translate expressions for the descriptor and data pointer of a SS. */
1252/*GCC ARRAYS*/
1253
1254static void
1255gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
1256{
1257 gfc_se se;
1258 tree tmp;
1259
1260 /* Get the descriptor for the array to be scalarized. */
6e45f57b 1261 gcc_assert (ss->expr->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
1262 gfc_init_se (&se, NULL);
1263 se.descriptor_only = 1;
1264 gfc_conv_expr_lhs (&se, ss->expr);
1265 gfc_add_block_to_block (block, &se.pre);
1266 ss->data.info.descriptor = se.expr;
40f20186 1267 ss->string_length = se.string_length;
6de9cd9a
DN
1268
1269 if (base)
1270 {
1271 /* Also the data pointer. */
1272 tmp = gfc_conv_array_data (se.expr);
1273 /* If this is a variable or address of a variable we use it directly.
1274 Otherwise we must evaluate it now to to avoid break dependency
1275 analysis by pulling the expressions for elemental array indices
1276 inside the loop. */
1277 if (!(DECL_P (tmp)
1278 || (TREE_CODE (tmp) == ADDR_EXPR
1279 && DECL_P (TREE_OPERAND (tmp, 0)))))
1280 tmp = gfc_evaluate_now (tmp, block);
1281 ss->data.info.data = tmp;
1282
1283 tmp = gfc_conv_array_offset (se.expr);
1284 ss->data.info.offset = gfc_evaluate_now (tmp, block);
1285 }
1286}
1287
1288
1f2959f0 1289/* Initialize a gfc_loopinfo structure. */
6de9cd9a
DN
1290
1291void
1292gfc_init_loopinfo (gfc_loopinfo * loop)
1293{
1294 int n;
1295
1296 memset (loop, 0, sizeof (gfc_loopinfo));
1297 gfc_init_block (&loop->pre);
1298 gfc_init_block (&loop->post);
1299
13413760 1300 /* Initially scalarize in order. */
6de9cd9a
DN
1301 for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
1302 loop->order[n] = n;
1303
1304 loop->ss = gfc_ss_terminator;
1305}
1306
1307
e7dc5b4f 1308/* Copies the loop variable info to a gfc_se structure. Does not copy the SS
6de9cd9a
DN
1309 chain. */
1310
1311void
1312gfc_copy_loopinfo_to_se (gfc_se * se, gfc_loopinfo * loop)
1313{
1314 se->loop = loop;
1315}
1316
1317
1318/* Return an expression for the data pointer of an array. */
1319
1320tree
1321gfc_conv_array_data (tree descriptor)
1322{
1323 tree type;
1324
1325 type = TREE_TYPE (descriptor);
1326 if (GFC_ARRAY_TYPE_P (type))
1327 {
1328 if (TREE_CODE (type) == POINTER_TYPE)
1329 return descriptor;
1330 else
1331 {
13413760 1332 /* Descriptorless arrays. */
6de9cd9a
DN
1333 return gfc_build_addr_expr (NULL, descriptor);
1334 }
1335 }
1336 else
1337 return gfc_conv_descriptor_data (descriptor);
1338}
1339
1340
1341/* Return an expression for the base offset of an array. */
1342
1343tree
1344gfc_conv_array_offset (tree descriptor)
1345{
1346 tree type;
1347
1348 type = TREE_TYPE (descriptor);
1349 if (GFC_ARRAY_TYPE_P (type))
1350 return GFC_TYPE_ARRAY_OFFSET (type);
1351 else
1352 return gfc_conv_descriptor_offset (descriptor);
1353}
1354
1355
1356/* Get an expression for the array stride. */
1357
1358tree
1359gfc_conv_array_stride (tree descriptor, int dim)
1360{
1361 tree tmp;
1362 tree type;
1363
1364 type = TREE_TYPE (descriptor);
1365
1366 /* For descriptorless arrays use the array size. */
1367 tmp = GFC_TYPE_ARRAY_STRIDE (type, dim);
1368 if (tmp != NULL_TREE)
1369 return tmp;
1370
1371 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
1372 return tmp;
1373}
1374
1375
1376/* Like gfc_conv_array_stride, but for the lower bound. */
1377
1378tree
1379gfc_conv_array_lbound (tree descriptor, int dim)
1380{
1381 tree tmp;
1382 tree type;
1383
1384 type = TREE_TYPE (descriptor);
1385
1386 tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
1387 if (tmp != NULL_TREE)
1388 return tmp;
1389
1390 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
1391 return tmp;
1392}
1393
1394
1395/* Like gfc_conv_array_stride, but for the upper bound. */
1396
1397tree
1398gfc_conv_array_ubound (tree descriptor, int dim)
1399{
1400 tree tmp;
1401 tree type;
1402
1403 type = TREE_TYPE (descriptor);
1404
1405 tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
1406 if (tmp != NULL_TREE)
1407 return tmp;
1408
1409 /* This should only ever happen when passing an assumed shape array
1410 as an actual parameter. The value will never be used. */
1411 if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
7ab92584 1412 return gfc_index_zero_node;
6de9cd9a
DN
1413
1414 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
1415 return tmp;
1416}
1417
1418
1419/* Translate an array reference. The descriptor should be in se->expr.
1420 Do not use this function, it wil be removed soon. */
1421/*GCC ARRAYS*/
1422
1423static void
1424gfc_conv_array_index_ref (gfc_se * se, tree pointer, tree * indices,
13413760 1425 tree offset, int dimen)
6de9cd9a
DN
1426{
1427 tree array;
1428 tree tmp;
1429 tree index;
1430 int n;
1431
1432 array = gfc_build_indirect_ref (pointer);
1433
1434 index = offset;
1435 for (n = 0; n < dimen; n++)
1436 {
1437 /* index = index + stride[n]*indices[n] */
1438 tmp = gfc_conv_array_stride (se->expr, n);
923ab88c 1439 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type, indices[n], tmp));
6de9cd9a 1440
923ab88c 1441 index = fold (build2 (PLUS_EXPR, gfc_array_index_type, index, tmp));
6de9cd9a
DN
1442 }
1443
1444 /* Result = data[index]. */
1445 tmp = gfc_build_array_ref (array, index);
1446
1447 /* Check we've used the correct number of dimensions. */
6e45f57b 1448 gcc_assert (TREE_CODE (TREE_TYPE (tmp)) != ARRAY_TYPE);
6de9cd9a
DN
1449
1450 se->expr = tmp;
1451}
1452
1453
1454/* Generate code to perform an array index bound check. */
1455
1456static tree
1457gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n)
1458{
1459 tree cond;
1460 tree fault;
1461 tree tmp;
1462
1463 if (!flag_bounds_check)
1464 return index;
1465
1466 index = gfc_evaluate_now (index, &se->pre);
1467 /* Check lower bound. */
1468 tmp = gfc_conv_array_lbound (descriptor, n);
923ab88c 1469 fault = fold (build2 (LT_EXPR, boolean_type_node, index, tmp));
6de9cd9a
DN
1470 /* Check upper bound. */
1471 tmp = gfc_conv_array_ubound (descriptor, n);
923ab88c
TS
1472 cond = fold (build2 (GT_EXPR, boolean_type_node, index, tmp));
1473 fault = fold (build2 (TRUTH_OR_EXPR, boolean_type_node, fault, cond));
6de9cd9a
DN
1474
1475 gfc_trans_runtime_check (fault, gfc_strconst_fault, &se->pre);
1476
1477 return index;
1478}
1479
1480
1481/* A reference to an array vector subscript. Uses recursion to handle nested
1482 vector subscripts. */
1483
1484static tree
1485gfc_conv_vector_array_index (gfc_se * se, tree index, gfc_ss * ss)
1486{
1487 tree descsave;
1488 tree indices[GFC_MAX_DIMENSIONS];
1489 gfc_array_ref *ar;
1490 gfc_ss_info *info;
1491 int n;
1492
6e45f57b 1493 gcc_assert (ss && ss->type == GFC_SS_VECTOR);
6de9cd9a
DN
1494
1495 /* Save the descriptor. */
1496 descsave = se->expr;
1497 info = &ss->data.info;
1498 se->expr = info->descriptor;
1499
1500 ar = &info->ref->u.ar;
1501 for (n = 0; n < ar->dimen; n++)
1502 {
1503 switch (ar->dimen_type[n])
1504 {
1505 case DIMEN_ELEMENT:
6e45f57b 1506 gcc_assert (info->subscript[n] != gfc_ss_terminator
6de9cd9a
DN
1507 && info->subscript[n]->type == GFC_SS_SCALAR);
1508 indices[n] = info->subscript[n]->data.scalar.expr;
1509 break;
1510
1511 case DIMEN_RANGE:
1512 indices[n] = index;
1513 break;
1514
1515 case DIMEN_VECTOR:
1516 index = gfc_conv_vector_array_index (se, index, info->subscript[n]);
1517
1518 indices[n] =
1519 gfc_trans_array_bound_check (se, info->descriptor, index, n);
1520 break;
1521
1522 default:
6e45f57b 1523 gcc_unreachable ();
6de9cd9a
DN
1524 }
1525 }
1526 /* Get the index from the vector. */
1527 gfc_conv_array_index_ref (se, info->data, indices, info->offset, ar->dimen);
1528 index = se->expr;
1529 /* Put the descriptor back. */
1530 se->expr = descsave;
1531
1532 return index;
1533}
1534
1535
1536/* Return the offset for an index. Performs bound checking for elemental
e7dc5b4f 1537 dimensions. Single element references are processed separately. */
6de9cd9a
DN
1538
1539static tree
1540gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
1541 gfc_array_ref * ar, tree stride)
1542{
1543 tree index;
1544
1545 /* Get the index into the array for this dimension. */
1546 if (ar)
1547 {
6e45f57b 1548 gcc_assert (ar->type != AR_ELEMENT);
6de9cd9a
DN
1549 if (ar->dimen_type[dim] == DIMEN_ELEMENT)
1550 {
6e45f57b 1551 gcc_assert (i == -1);
6de9cd9a 1552 /* Elemental dimension. */
6e45f57b 1553 gcc_assert (info->subscript[dim]
6de9cd9a
DN
1554 && info->subscript[dim]->type == GFC_SS_SCALAR);
1555 /* We've already translated this value outside the loop. */
1556 index = info->subscript[dim]->data.scalar.expr;
1557
1558 index =
1559 gfc_trans_array_bound_check (se, info->descriptor, index, dim);
1560 }
1561 else
1562 {
1563 /* Scalarized dimension. */
6e45f57b 1564 gcc_assert (info && se->loop);
6de9cd9a
DN
1565
1566 /* Multiply the loop variable by the stride and dela. */
1567 index = se->loop->loopvar[i];
923ab88c
TS
1568 index = fold (build2 (MULT_EXPR, gfc_array_index_type, index,
1569 info->stride[i]));
1570 index = fold (build2 (PLUS_EXPR, gfc_array_index_type, index,
1571 info->delta[i]));
6de9cd9a
DN
1572
1573 if (ar->dimen_type[dim] == DIMEN_VECTOR)
1574 {
1575 /* Handle vector subscripts. */
1576 index = gfc_conv_vector_array_index (se, index,
1577 info->subscript[dim]);
1578 index =
1579 gfc_trans_array_bound_check (se, info->descriptor, index,
1580 dim);
1581 }
1582 else
6e45f57b 1583 gcc_assert (ar->dimen_type[dim] == DIMEN_RANGE);
6de9cd9a
DN
1584 }
1585 }
1586 else
1587 {
e9cfef64 1588 /* Temporary array or derived type component. */
6e45f57b 1589 gcc_assert (se->loop);
6de9cd9a 1590 index = se->loop->loopvar[se->loop->order[i]];
e9cfef64 1591 if (!integer_zerop (info->delta[i]))
923ab88c
TS
1592 index = fold (build2 (PLUS_EXPR, gfc_array_index_type,
1593 index, info->delta[i]));
6de9cd9a
DN
1594 }
1595
1596 /* Multiply by the stride. */
923ab88c 1597 index = fold (build2 (MULT_EXPR, gfc_array_index_type, index, stride));
6de9cd9a
DN
1598
1599 return index;
1600}
1601
1602
1603/* Build a scalarized reference to an array. */
1604
1605static void
1606gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
1607{
1608 gfc_ss_info *info;
1609 tree index;
1610 tree tmp;
1611 int n;
1612
1613 info = &se->ss->data.info;
1614 if (ar)
1615 n = se->loop->order[0];
1616 else
1617 n = 0;
1618
1619 index = gfc_conv_array_index_offset (se, info, info->dim[n], n, ar,
1620 info->stride0);
1621 /* Add the offset for this dimension to the stored offset for all other
1622 dimensions. */
923ab88c 1623 index = fold (build2 (PLUS_EXPR, gfc_array_index_type, index, info->offset));
6de9cd9a
DN
1624
1625 tmp = gfc_build_indirect_ref (info->data);
1626 se->expr = gfc_build_array_ref (tmp, index);
1627}
1628
1629
1630/* Translate access of temporary array. */
1631
1632void
1633gfc_conv_tmp_array_ref (gfc_se * se)
1634{
40f20186 1635 se->string_length = se->ss->string_length;
6de9cd9a
DN
1636 gfc_conv_scalarized_array_ref (se, NULL);
1637}
1638
1639
1640/* Build an array reference. se->expr already holds the array descriptor.
1641 This should be either a variable, indirect variable reference or component
1642 reference. For arrays which do not have a descriptor, se->expr will be
1643 the data pointer.
1644 a(i, j, k) = base[offset + i * stride[0] + j * stride[1] + k * stride[2]]*/
1645
1646void
1647gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar)
1648{
1649 int n;
1650 tree index;
1651 tree tmp;
1652 tree stride;
1653 tree fault;
1654 gfc_se indexse;
1655
e7dc5b4f 1656 /* Handle scalarized references separately. */
6de9cd9a
DN
1657 if (ar->type != AR_ELEMENT)
1658 {
1659 gfc_conv_scalarized_array_ref (se, ar);
1660 return;
1661 }
1662
7ab92584 1663 index = gfc_index_zero_node;
6de9cd9a 1664
7ab92584 1665 fault = gfc_index_zero_node;
6de9cd9a
DN
1666
1667 /* Calculate the offsets from all the dimensions. */
1668 for (n = 0; n < ar->dimen; n++)
1669 {
1f2959f0 1670 /* Calculate the index for this dimension. */
6de9cd9a
DN
1671 gfc_init_se (&indexse, NULL);
1672 gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
1673 gfc_add_block_to_block (&se->pre, &indexse.pre);
1674
1675 if (flag_bounds_check)
1676 {
1677 /* Check array bounds. */
1678 tree cond;
1679
1680 indexse.expr = gfc_evaluate_now (indexse.expr, &se->pre);
1681
1682 tmp = gfc_conv_array_lbound (se->expr, n);
923ab88c
TS
1683 cond = fold (build2 (LT_EXPR, boolean_type_node,
1684 indexse.expr, tmp));
6de9cd9a 1685 fault =
923ab88c 1686 fold (build2 (TRUTH_OR_EXPR, boolean_type_node, fault, cond));
6de9cd9a
DN
1687
1688 tmp = gfc_conv_array_ubound (se->expr, n);
923ab88c
TS
1689 cond = fold (build2 (GT_EXPR, boolean_type_node,
1690 indexse.expr, tmp));
6de9cd9a 1691 fault =
923ab88c 1692 fold (build2 (TRUTH_OR_EXPR, boolean_type_node, fault, cond));
6de9cd9a
DN
1693 }
1694
1695 /* Multiply the index by the stride. */
1696 stride = gfc_conv_array_stride (se->expr, n);
923ab88c
TS
1697 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type, indexse.expr,
1698 stride));
6de9cd9a
DN
1699
1700 /* And add it to the total. */
923ab88c 1701 index = fold (build2 (PLUS_EXPR, gfc_array_index_type, index, tmp));
6de9cd9a
DN
1702 }
1703
1704 if (flag_bounds_check)
1705 gfc_trans_runtime_check (fault, gfc_strconst_fault, &se->pre);
1706
1707 tmp = gfc_conv_array_offset (se->expr);
1708 if (!integer_zerop (tmp))
923ab88c 1709 index = fold (build2 (PLUS_EXPR, gfc_array_index_type, index, tmp));
6de9cd9a
DN
1710
1711 /* Access the calculated element. */
1712 tmp = gfc_conv_array_data (se->expr);
1713 tmp = gfc_build_indirect_ref (tmp);
1714 se->expr = gfc_build_array_ref (tmp, index);
1715}
1716
1717
1718/* Generate the code to be executed immediately before entering a
1719 scalarization loop. */
1720
1721static void
1722gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
1723 stmtblock_t * pblock)
1724{
1725 tree index;
1726 tree stride;
1727 gfc_ss_info *info;
1728 gfc_ss *ss;
1729 gfc_se se;
1730 int i;
1731
1732 /* This code will be executed before entering the scalarization loop
1733 for this dimension. */
1734 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
1735 {
1736 if ((ss->useflags & flag) == 0)
1737 continue;
1738
1739 if (ss->type != GFC_SS_SECTION
e9cfef64
PB
1740 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
1741 && ss->type != GFC_SS_COMPONENT)
6de9cd9a
DN
1742 continue;
1743
1744 info = &ss->data.info;
1745
1746 if (dim >= info->dimen)
1747 continue;
1748
1749 if (dim == info->dimen - 1)
1750 {
1751 /* For the outermost loop calculate the offset due to any
1752 elemental dimensions. It will have been initialized with the
1753 base offset of the array. */
1754 if (info->ref)
1755 {
1756 for (i = 0; i < info->ref->u.ar.dimen; i++)
1757 {
1758 if (info->ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
1759 continue;
1760
1761 gfc_init_se (&se, NULL);
1762 se.loop = loop;
1763 se.expr = info->descriptor;
1764 stride = gfc_conv_array_stride (info->descriptor, i);
1765 index = gfc_conv_array_index_offset (&se, info, i, -1,
1766 &info->ref->u.ar,
1767 stride);
1768 gfc_add_block_to_block (pblock, &se.pre);
1769
923ab88c
TS
1770 info->offset = fold (build2 (PLUS_EXPR, gfc_array_index_type,
1771 info->offset, index));
6de9cd9a
DN
1772 info->offset = gfc_evaluate_now (info->offset, pblock);
1773 }
1774
1775 i = loop->order[0];
1776 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
1777 }
1778 else
1779 stride = gfc_conv_array_stride (info->descriptor, 0);
1780
1781 /* Calculate the stride of the innermost loop. Hopefully this will
1782 allow the backend optimizers to do their stuff more effectively.
1783 */
1784 info->stride0 = gfc_evaluate_now (stride, pblock);
1785 }
1786 else
1787 {
1788 /* Add the offset for the previous loop dimension. */
1789 gfc_array_ref *ar;
1790
1791 if (info->ref)
1792 {
1793 ar = &info->ref->u.ar;
1794 i = loop->order[dim + 1];
1795 }
1796 else
1797 {
1798 ar = NULL;
1799 i = dim + 1;
1800 }
1801
1802 gfc_init_se (&se, NULL);
1803 se.loop = loop;
1804 se.expr = info->descriptor;
1805 stride = gfc_conv_array_stride (info->descriptor, info->dim[i]);
1806 index = gfc_conv_array_index_offset (&se, info, info->dim[i], i,
1807 ar, stride);
1808 gfc_add_block_to_block (pblock, &se.pre);
923ab88c
TS
1809 info->offset = fold (build2 (PLUS_EXPR, gfc_array_index_type,
1810 info->offset, index));
6de9cd9a
DN
1811 info->offset = gfc_evaluate_now (info->offset, pblock);
1812 }
1813
e7dc5b4f 1814 /* Remember this offset for the second loop. */
6de9cd9a
DN
1815 if (dim == loop->temp_dim - 1)
1816 info->saved_offset = info->offset;
1817 }
1818}
1819
1820
1821/* Start a scalarized expression. Creates a scope and declares loop
1822 variables. */
1823
1824void
1825gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
1826{
1827 int dim;
1828 int n;
1829 int flags;
1830
6e45f57b 1831 gcc_assert (!loop->array_parameter);
6de9cd9a
DN
1832
1833 for (dim = loop->dimen - 1; dim >= 0; dim--)
1834 {
1835 n = loop->order[dim];
1836
1837 gfc_start_block (&loop->code[n]);
1838
1839 /* Create the loop variable. */
1840 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "S");
1841
1842 if (dim < loop->temp_dim)
1843 flags = 3;
1844 else
1845 flags = 1;
1846 /* Calculate values that will be constant within this loop. */
1847 gfc_trans_preloop_setup (loop, dim, flags, &loop->code[n]);
1848 }
1849 gfc_start_block (pbody);
1850}
1851
1852
1853/* Generates the actual loop code for a scalarization loop. */
1854
1855static void
1856gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
1857 stmtblock_t * pbody)
1858{
1859 stmtblock_t block;
1860 tree cond;
1861 tree tmp;
1862 tree loopbody;
1863 tree exit_label;
1864
1865 loopbody = gfc_finish_block (pbody);
1866
1867 /* Initialize the loopvar. */
1868 gfc_add_modify_expr (&loop->code[n], loop->loopvar[n], loop->from[n]);
1869
1870 exit_label = gfc_build_label_decl (NULL_TREE);
1871
1872 /* Generate the loop body. */
1873 gfc_init_block (&block);
1874
1875 /* The exit condition. */
923ab88c 1876 cond = build2 (GT_EXPR, boolean_type_node, loop->loopvar[n], loop->to[n]);
6de9cd9a
DN
1877 tmp = build1_v (GOTO_EXPR, exit_label);
1878 TREE_USED (exit_label) = 1;
923ab88c 1879 tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
6de9cd9a
DN
1880 gfc_add_expr_to_block (&block, tmp);
1881
1882 /* The main body. */
1883 gfc_add_expr_to_block (&block, loopbody);
1884
1885 /* Increment the loopvar. */
923ab88c
TS
1886 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
1887 loop->loopvar[n], gfc_index_one_node);
6de9cd9a
DN
1888 gfc_add_modify_expr (&block, loop->loopvar[n], tmp);
1889
1890 /* Build the loop. */
1891 tmp = gfc_finish_block (&block);
923ab88c 1892 tmp = build1_v (LOOP_EXPR, tmp);
6de9cd9a
DN
1893 gfc_add_expr_to_block (&loop->code[n], tmp);
1894
1895 /* Add the exit label. */
1896 tmp = build1_v (LABEL_EXPR, exit_label);
1897 gfc_add_expr_to_block (&loop->code[n], tmp);
1898}
1899
1900
1901/* Finishes and generates the loops for a scalarized expression. */
1902
1903void
1904gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
1905{
1906 int dim;
1907 int n;
1908 gfc_ss *ss;
1909 stmtblock_t *pblock;
1910 tree tmp;
1911
1912 pblock = body;
1913 /* Generate the loops. */
1914 for (dim = 0; dim < loop->dimen; dim++)
1915 {
1916 n = loop->order[dim];
1917 gfc_trans_scalarized_loop_end (loop, n, pblock);
1918 loop->loopvar[n] = NULL_TREE;
1919 pblock = &loop->code[n];
1920 }
1921
1922 tmp = gfc_finish_block (pblock);
1923 gfc_add_expr_to_block (&loop->pre, tmp);
1924
1925 /* Clear all the used flags. */
1926 for (ss = loop->ss; ss; ss = ss->loop_chain)
1927 ss->useflags = 0;
1928}
1929
1930
1931/* Finish the main body of a scalarized expression, and start the secondary
1932 copying body. */
1933
1934void
1935gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
1936{
1937 int dim;
1938 int n;
1939 stmtblock_t *pblock;
1940 gfc_ss *ss;
1941
1942 pblock = body;
1943 /* We finish as many loops as are used by the temporary. */
1944 for (dim = 0; dim < loop->temp_dim - 1; dim++)
1945 {
1946 n = loop->order[dim];
1947 gfc_trans_scalarized_loop_end (loop, n, pblock);
1948 loop->loopvar[n] = NULL_TREE;
1949 pblock = &loop->code[n];
1950 }
1951
1952 /* We don't want to finish the outermost loop entirely. */
1953 n = loop->order[loop->temp_dim - 1];
1954 gfc_trans_scalarized_loop_end (loop, n, pblock);
1955
1956 /* Restore the initial offsets. */
1957 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
1958 {
1959 if ((ss->useflags & 2) == 0)
1960 continue;
1961
1962 if (ss->type != GFC_SS_SECTION
e9cfef64
PB
1963 && ss->type != GFC_SS_FUNCTION && ss->type != GFC_SS_CONSTRUCTOR
1964 && ss->type != GFC_SS_COMPONENT)
6de9cd9a
DN
1965 continue;
1966
1967 ss->data.info.offset = ss->data.info.saved_offset;
1968 }
1969
1970 /* Restart all the inner loops we just finished. */
1971 for (dim = loop->temp_dim - 2; dim >= 0; dim--)
1972 {
1973 n = loop->order[dim];
1974
1975 gfc_start_block (&loop->code[n]);
1976
1977 loop->loopvar[n] = gfc_create_var (gfc_array_index_type, "Q");
1978
1979 gfc_trans_preloop_setup (loop, dim, 2, &loop->code[n]);
1980 }
1981
1982 /* Start a block for the secondary copying code. */
1983 gfc_start_block (body);
1984}
1985
1986
1987/* Calculate the upper bound of an array section. */
1988
1989static tree
1990gfc_conv_section_upper_bound (gfc_ss * ss, int n, stmtblock_t * pblock)
1991{
1992 int dim;
1993 gfc_ss *vecss;
1994 gfc_expr *end;
1995 tree desc;
1996 tree bound;
1997 gfc_se se;
1998
6e45f57b 1999 gcc_assert (ss->type == GFC_SS_SECTION);
6de9cd9a
DN
2000
2001 /* For vector array subscripts we want the size of the vector. */
2002 dim = ss->data.info.dim[n];
2003 vecss = ss;
2004 while (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2005 {
2006 vecss = vecss->data.info.subscript[dim];
6e45f57b 2007 gcc_assert (vecss && vecss->type == GFC_SS_VECTOR);
6de9cd9a
DN
2008 dim = vecss->data.info.dim[0];
2009 }
2010
6e45f57b 2011 gcc_assert (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
6de9cd9a
DN
2012 end = vecss->data.info.ref->u.ar.end[dim];
2013 desc = vecss->data.info.descriptor;
2014
2015 if (end)
2016 {
2017 /* The upper bound was specified. */
2018 gfc_init_se (&se, NULL);
2019 gfc_conv_expr_type (&se, end, gfc_array_index_type);
2020 gfc_add_block_to_block (pblock, &se.pre);
2021 bound = se.expr;
2022 }
2023 else
2024 {
f7b529fa 2025 /* No upper bound was specified, so use the bound of the array. */
6de9cd9a
DN
2026 bound = gfc_conv_array_ubound (desc, dim);
2027 }
2028
2029 return bound;
2030}
2031
2032
2033/* Calculate the lower bound of an array section. */
2034
2035static void
2036gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int n)
2037{
2038 gfc_expr *start;
2039 gfc_expr *stride;
2040 gfc_ss *vecss;
2041 tree desc;
2042 gfc_se se;
2043 gfc_ss_info *info;
2044 int dim;
2045
2046 info = &ss->data.info;
2047
2048 dim = info->dim[n];
2049
2050 /* For vector array subscripts we want the size of the vector. */
2051 vecss = ss;
2052 while (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2053 {
2054 vecss = vecss->data.info.subscript[dim];
6e45f57b 2055 gcc_assert (vecss && vecss->type == GFC_SS_VECTOR);
6de9cd9a
DN
2056 /* Get the descriptors for the vector subscripts as well. */
2057 if (!vecss->data.info.descriptor)
2058 gfc_conv_ss_descriptor (&loop->pre, vecss, !loop->array_parameter);
2059 dim = vecss->data.info.dim[0];
2060 }
2061
6e45f57b 2062 gcc_assert (vecss->data.info.ref->u.ar.dimen_type[dim] == DIMEN_RANGE);
6de9cd9a
DN
2063 start = vecss->data.info.ref->u.ar.start[dim];
2064 stride = vecss->data.info.ref->u.ar.stride[dim];
2065 desc = vecss->data.info.descriptor;
2066
2067 /* Calculate the start of the range. For vector subscripts this will
2068 be the range of the vector. */
2069 if (start)
2070 {
2071 /* Specified section start. */
2072 gfc_init_se (&se, NULL);
2073 gfc_conv_expr_type (&se, start, gfc_array_index_type);
2074 gfc_add_block_to_block (&loop->pre, &se.pre);
2075 info->start[n] = se.expr;
2076 }
2077 else
2078 {
2079 /* No lower bound specified so use the bound of the array. */
2080 info->start[n] = gfc_conv_array_lbound (desc, dim);
2081 }
2082 info->start[n] = gfc_evaluate_now (info->start[n], &loop->pre);
2083
2084 /* Calculate the stride. */
2085 if (stride == NULL)
7ab92584 2086 info->stride[n] = gfc_index_one_node;
6de9cd9a
DN
2087 else
2088 {
2089 gfc_init_se (&se, NULL);
2090 gfc_conv_expr_type (&se, stride, gfc_array_index_type);
2091 gfc_add_block_to_block (&loop->pre, &se.pre);
2092 info->stride[n] = gfc_evaluate_now (se.expr, &loop->pre);
2093 }
2094}
2095
2096
2097/* Calculates the range start and stride for a SS chain. Also gets the
2098 descriptor and data pointer. The range of vector subscripts is the size
2099 of the vector. Array bounds are also checked. */
2100
2101void
2102gfc_conv_ss_startstride (gfc_loopinfo * loop)
2103{
2104 int n;
2105 tree tmp;
2106 gfc_ss *ss;
2107 gfc_ss *vecss;
2108 tree desc;
2109
2110 loop->dimen = 0;
2111 /* Determine the rank of the loop. */
2112 for (ss = loop->ss;
2113 ss != gfc_ss_terminator && loop->dimen == 0; ss = ss->loop_chain)
2114 {
2115 switch (ss->type)
2116 {
2117 case GFC_SS_SECTION:
2118 case GFC_SS_CONSTRUCTOR:
2119 case GFC_SS_FUNCTION:
e9cfef64 2120 case GFC_SS_COMPONENT:
6de9cd9a
DN
2121 loop->dimen = ss->data.info.dimen;
2122 break;
2123
2124 default:
2125 break;
2126 }
2127 }
2128
2129 if (loop->dimen == 0)
2130 gfc_todo_error ("Unable to determine rank of expression");
2131
2132
13413760 2133 /* Loop over all the SS in the chain. */
6de9cd9a
DN
2134 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2135 {
e9cfef64
PB
2136 if (ss->expr && ss->expr->shape && !ss->shape)
2137 ss->shape = ss->expr->shape;
2138
6de9cd9a
DN
2139 switch (ss->type)
2140 {
2141 case GFC_SS_SECTION:
2142 /* Get the descriptor for the array. */
2143 gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
2144
2145 for (n = 0; n < ss->data.info.dimen; n++)
2146 gfc_conv_section_startstride (loop, ss, n);
2147 break;
2148
2149 case GFC_SS_CONSTRUCTOR:
2150 case GFC_SS_FUNCTION:
2151 for (n = 0; n < ss->data.info.dimen; n++)
2152 {
7ab92584
SB
2153 ss->data.info.start[n] = gfc_index_zero_node;
2154 ss->data.info.stride[n] = gfc_index_one_node;
6de9cd9a
DN
2155 }
2156 break;
2157
2158 default:
2159 break;
2160 }
2161 }
2162
2163 /* The rest is just runtime bound checking. */
2164 if (flag_bounds_check)
2165 {
2166 stmtblock_t block;
2167 tree fault;
2168 tree bound;
2169 tree end;
2170 tree size[GFC_MAX_DIMENSIONS];
2171 gfc_ss_info *info;
2172 int dim;
2173
2174 gfc_start_block (&block);
2175
2176 fault = integer_zero_node;
2177 for (n = 0; n < loop->dimen; n++)
2178 size[n] = NULL_TREE;
2179
2180 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2181 {
2182 if (ss->type != GFC_SS_SECTION)
2183 continue;
2184
2185 /* TODO: range checking for mapped dimensions. */
2186 info = &ss->data.info;
2187
2188 /* This only checks scalarized dimensions, elemental dimensions are
2189 checked later. */
2190 for (n = 0; n < loop->dimen; n++)
2191 {
2192 dim = info->dim[n];
2193 vecss = ss;
2194 while (vecss->data.info.ref->u.ar.dimen_type[dim]
2195 == DIMEN_VECTOR)
2196 {
2197 vecss = vecss->data.info.subscript[dim];
6e45f57b 2198 gcc_assert (vecss && vecss->type == GFC_SS_VECTOR);
6de9cd9a
DN
2199 dim = vecss->data.info.dim[0];
2200 }
6e45f57b 2201 gcc_assert (vecss->data.info.ref->u.ar.dimen_type[dim]
6de9cd9a
DN
2202 == DIMEN_RANGE);
2203 desc = vecss->data.info.descriptor;
2204
2205 /* Check lower bound. */
2206 bound = gfc_conv_array_lbound (desc, dim);
2207 tmp = info->start[n];
923ab88c
TS
2208 tmp = fold (build2 (LT_EXPR, boolean_type_node, tmp, bound));
2209 fault = fold (build2 (TRUTH_OR_EXPR, boolean_type_node, fault,
2210 tmp));
6de9cd9a
DN
2211
2212 /* Check the upper bound. */
2213 bound = gfc_conv_array_ubound (desc, dim);
2214 end = gfc_conv_section_upper_bound (ss, n, &block);
923ab88c
TS
2215 tmp = fold (build2 (GT_EXPR, boolean_type_node, end, bound));
2216 fault = fold (build2 (TRUTH_OR_EXPR, boolean_type_node, fault,
2217 tmp));
6de9cd9a
DN
2218
2219 /* Check the section sizes match. */
923ab88c
TS
2220 tmp = fold (build2 (MINUS_EXPR, gfc_array_index_type, end,
2221 info->start[n]));
2222 tmp = fold (build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
2223 info->stride[n]));
6de9cd9a
DN
2224 /* We remember the size of the first section, and check all the
2225 others against this. */
2226 if (size[n])
2227 {
2228 tmp =
923ab88c 2229 fold (build2 (NE_EXPR, boolean_type_node, tmp, size[n]));
6de9cd9a 2230 fault =
923ab88c 2231 build2 (TRUTH_OR_EXPR, boolean_type_node, fault, tmp);
6de9cd9a
DN
2232 }
2233 else
2234 size[n] = gfc_evaluate_now (tmp, &block);
2235 }
2236 }
2237 gfc_trans_runtime_check (fault, gfc_strconst_bounds, &block);
2238
2239 tmp = gfc_finish_block (&block);
2240 gfc_add_expr_to_block (&loop->pre, tmp);
2241 }
2242}
2243
2244
13795658 2245/* Return true if the two SS could be aliased, i.e. both point to the same data
6de9cd9a
DN
2246 object. */
2247/* TODO: resolve aliases based on frontend expressions. */
2248
2249static int
2250gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
2251{
2252 gfc_ref *lref;
2253 gfc_ref *rref;
2254 gfc_symbol *lsym;
2255 gfc_symbol *rsym;
2256
2257 lsym = lss->expr->symtree->n.sym;
2258 rsym = rss->expr->symtree->n.sym;
2259 if (gfc_symbols_could_alias (lsym, rsym))
2260 return 1;
2261
2262 if (rsym->ts.type != BT_DERIVED
2263 && lsym->ts.type != BT_DERIVED)
2264 return 0;
2265
13413760 2266 /* For derived types we must check all the component types. We can ignore
6de9cd9a
DN
2267 array references as these will have the same base type as the previous
2268 component ref. */
2269 for (lref = lss->expr->ref; lref != lss->data.info.ref; lref = lref->next)
2270 {
2271 if (lref->type != REF_COMPONENT)
2272 continue;
2273
2274 if (gfc_symbols_could_alias (lref->u.c.sym, rsym))
2275 return 1;
2276
2277 for (rref = rss->expr->ref; rref != rss->data.info.ref;
2278 rref = rref->next)
2279 {
2280 if (rref->type != REF_COMPONENT)
2281 continue;
2282
2283 if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym))
2284 return 1;
2285 }
2286 }
2287
2288 for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next)
2289 {
2290 if (rref->type != REF_COMPONENT)
2291 break;
2292
2293 if (gfc_symbols_could_alias (rref->u.c.sym, lsym))
2294 return 1;
2295 }
2296
2297 return 0;
2298}
2299
2300
2301/* Resolve array data dependencies. Creates a temporary if required. */
2302/* TODO: Calc dependencies with gfc_expr rather than gfc_ss, and move to
2303 dependency.c. */
2304
2305void
2306gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
2307 gfc_ss * rss)
2308{
2309 gfc_ss *ss;
2310 gfc_ref *lref;
2311 gfc_ref *rref;
2312 gfc_ref *aref;
2313 int nDepend = 0;
2314 int temp_dim = 0;
2315
2316 loop->temp_ss = NULL;
2317 aref = dest->data.info.ref;
2318 temp_dim = 0;
2319
2320 for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
2321 {
2322 if (ss->type != GFC_SS_SECTION)
2323 continue;
2324
2325 if (gfc_could_be_alias (dest, ss))
2326 {
2327 nDepend = 1;
2328 break;
2329 }
2330
2331 if (dest->expr->symtree->n.sym == ss->expr->symtree->n.sym)
2332 {
2333 lref = dest->expr->ref;
2334 rref = ss->expr->ref;
2335
2336 nDepend = gfc_dep_resolver (lref, rref);
2337#if 0
2338 /* TODO : loop shifting. */
2339 if (nDepend == 1)
2340 {
2341 /* Mark the dimensions for LOOP SHIFTING */
2342 for (n = 0; n < loop->dimen; n++)
2343 {
2344 int dim = dest->data.info.dim[n];
2345
2346 if (lref->u.ar.dimen_type[dim] == DIMEN_VECTOR)
2347 depends[n] = 2;
2348 else if (! gfc_is_same_range (&lref->u.ar,
2349 &rref->u.ar, dim, 0))
2350 depends[n] = 1;
2351 }
2352
13413760 2353 /* Put all the dimensions with dependencies in the
6de9cd9a
DN
2354 innermost loops. */
2355 dim = 0;
2356 for (n = 0; n < loop->dimen; n++)
2357 {
6e45f57b 2358 gcc_assert (loop->order[n] == n);
6de9cd9a
DN
2359 if (depends[n])
2360 loop->order[dim++] = n;
2361 }
2362 temp_dim = dim;
2363 for (n = 0; n < loop->dimen; n++)
2364 {
2365 if (! depends[n])
2366 loop->order[dim++] = n;
2367 }
2368
6e45f57b 2369 gcc_assert (dim == loop->dimen);
6de9cd9a
DN
2370 break;
2371 }
2372#endif
2373 }
2374 }
2375
2376 if (nDepend == 1)
2377 {
2378 loop->temp_ss = gfc_get_ss ();
2379 loop->temp_ss->type = GFC_SS_TEMP;
2380 loop->temp_ss->data.temp.type =
2381 gfc_get_element_type (TREE_TYPE (dest->data.info.descriptor));
40f20186 2382 loop->temp_ss->string_length = NULL_TREE;
6de9cd9a
DN
2383 loop->temp_ss->data.temp.dimen = loop->dimen;
2384 loop->temp_ss->next = gfc_ss_terminator;
2385 gfc_add_ss_to_loop (loop, loop->temp_ss);
2386 }
2387 else
2388 loop->temp_ss = NULL;
2389}
2390
2391
1f2959f0 2392/* Initialize the scalarization loop. Creates the loop variables. Determines
6de9cd9a
DN
2393 the range of the loop variables. Creates a temporary if required.
2394 Calculates how to transform from loop variables to array indices for each
2395 expression. Also generates code for scalar expressions which have been
f7b529fa 2396 moved outside the loop. */
6de9cd9a
DN
2397
2398void
2399gfc_conv_loop_setup (gfc_loopinfo * loop)
2400{
2401 int n;
2402 int dim;
2403 gfc_ss_info *info;
2404 gfc_ss_info *specinfo;
2405 gfc_ss *ss;
2406 tree tmp;
2407 tree len;
2408 gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
2409 mpz_t *cshape;
2410 mpz_t i;
2411
2412 mpz_init (i);
2413 for (n = 0; n < loop->dimen; n++)
2414 {
2415 loopspec[n] = NULL;
2416 /* We use one SS term, and use that to determine the bounds of the
2417 loop for this dimension. We try to pick the simplest term. */
2418 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2419 {
e9cfef64 2420 if (ss->shape)
6de9cd9a
DN
2421 {
2422 /* The frontend has worked out the size for us. */
2423 loopspec[n] = ss;
2424 continue;
2425 }
2426
2427 if (ss->type == GFC_SS_CONSTRUCTOR)
2428 {
e9cfef64 2429 /* An unknown size constructor will always be rank one.
40f20186 2430 Higher rank constructors will either have known shape,
e9cfef64 2431 or still be wrapped in a call to reshape. */
6e45f57b 2432 gcc_assert (loop->dimen == 1);
13413760
TS
2433 /* Try to figure out the size of the constructor. */
2434 /* TODO: avoid this by making the frontend set the shape. */
6de9cd9a 2435 gfc_get_array_cons_size (&i, ss->expr->value.constructor);
f7b529fa 2436 /* A negative value means we failed. */
6de9cd9a
DN
2437 if (mpz_sgn (i) > 0)
2438 {
2439 mpz_sub_ui (i, i, 1);
2440 loop->to[n] =
2441 gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
2442 loopspec[n] = ss;
2443 }
2444 continue;
2445 }
2446
fc90a8f2 2447 /* TODO: Pick the best bound if we have a choice between a
e9cfef64 2448 function and something else. */
fc90a8f2
PB
2449 if (ss->type == GFC_SS_FUNCTION)
2450 {
2451 loopspec[n] = ss;
2452 continue;
2453 }
2454
6de9cd9a
DN
2455 if (ss->type != GFC_SS_SECTION)
2456 continue;
2457
6de9cd9a
DN
2458 if (loopspec[n])
2459 specinfo = &loopspec[n]->data.info;
2460 else
2461 specinfo = NULL;
2462 info = &ss->data.info;
2463
2464 /* Criteria for choosing a loop specifier (most important first):
2465 stride of one
2466 known stride
2467 known lower bound
2468 known upper bound
2469 */
2470 if (!specinfo)
2471 loopspec[n] = ss;
40f20186 2472 /* TODO: Is != constructor correct? */
6de9cd9a
DN
2473 else if (loopspec[n]->type != GFC_SS_CONSTRUCTOR)
2474 {
2475 if (integer_onep (info->stride[n])
2476 && !integer_onep (specinfo->stride[n]))
2477 loopspec[n] = ss;
2478 else if (INTEGER_CST_P (info->stride[n])
2479 && !INTEGER_CST_P (specinfo->stride[n]))
2480 loopspec[n] = ss;
2481 else if (INTEGER_CST_P (info->start[n])
2482 && !INTEGER_CST_P (specinfo->start[n]))
2483 loopspec[n] = ss;
2484 /* We don't work out the upper bound.
2485 else if (INTEGER_CST_P (info->finish[n])
2486 && ! INTEGER_CST_P (specinfo->finish[n]))
2487 loopspec[n] = ss; */
2488 }
2489 }
2490
2491 if (!loopspec[n])
2492 gfc_todo_error ("Unable to find scalarization loop specifier");
2493
2494 info = &loopspec[n]->data.info;
2495
2496 /* Set the extents of this range. */
e9cfef64 2497 cshape = loopspec[n]->shape;
6de9cd9a
DN
2498 if (cshape && INTEGER_CST_P (info->start[n])
2499 && INTEGER_CST_P (info->stride[n]))
2500 {
2501 loop->from[n] = info->start[n];
2502 mpz_set (i, cshape[n]);
2503 mpz_sub_ui (i, i, 1);
2504 /* To = from + (size - 1) * stride. */
2505 tmp = gfc_conv_mpz_to_tree (i, gfc_index_integer_kind);
2506 if (!integer_onep (info->stride[n]))
923ab88c
TS
2507 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type,
2508 tmp, info->stride[n]));
2509 loop->to[n] = fold (build2 (PLUS_EXPR, gfc_array_index_type,
2510 loop->from[n], tmp));
6de9cd9a
DN
2511 }
2512 else
2513 {
2514 loop->from[n] = info->start[n];
2515 switch (loopspec[n]->type)
2516 {
2517 case GFC_SS_CONSTRUCTOR:
6e45f57b
PB
2518 gcc_assert (info->dimen == 1);
2519 gcc_assert (loop->to[n]);
6de9cd9a
DN
2520 break;
2521
2522 case GFC_SS_SECTION:
2523 loop->to[n] = gfc_conv_section_upper_bound (loopspec[n], n,
2524 &loop->pre);
2525 break;
2526
fc90a8f2
PB
2527 case GFC_SS_FUNCTION:
2528 /* The loop bound will be set when we generate the call. */
6e45f57b 2529 gcc_assert (loop->to[n] == NULL_TREE);
fc90a8f2
PB
2530 break;
2531
6de9cd9a 2532 default:
6e45f57b 2533 gcc_unreachable ();
6de9cd9a
DN
2534 }
2535 }
2536
2537 /* Transform everything so we have a simple incrementing variable. */
2538 if (integer_onep (info->stride[n]))
7ab92584 2539 info->delta[n] = gfc_index_zero_node;
6de9cd9a
DN
2540 else
2541 {
2542 /* Set the delta for this section. */
2543 info->delta[n] = gfc_evaluate_now (loop->from[n], &loop->pre);
2544 /* Number of iterations is (end - start + step) / step.
2545 with start = 0, this simplifies to
2546 last = end / step;
2547 for (i = 0; i<=last; i++){...}; */
923ab88c
TS
2548 tmp = fold (build2 (MINUS_EXPR, gfc_array_index_type,
2549 loop->to[n], loop->from[n]));
2550 tmp = fold (build2 (TRUNC_DIV_EXPR, gfc_array_index_type,
2551 tmp, info->stride[n]));
6de9cd9a
DN
2552 loop->to[n] = gfc_evaluate_now (tmp, &loop->pre);
2553 /* Make the loop variable start at 0. */
7ab92584 2554 loop->from[n] = gfc_index_zero_node;
6de9cd9a
DN
2555 }
2556 }
2557
fc90a8f2
PB
2558 /* Add all the scalar code that can be taken out of the loops.
2559 This may include calculating the loop bounds, so do it before
2560 allocating the temporary. */
2561 gfc_add_loop_ss_code (loop, loop->ss, false);
2562
6de9cd9a
DN
2563 /* If we want a temporary then create it. */
2564 if (loop->temp_ss != NULL)
2565 {
6e45f57b 2566 gcc_assert (loop->temp_ss->type == GFC_SS_TEMP);
6de9cd9a 2567 tmp = loop->temp_ss->data.temp.type;
40f20186 2568 len = loop->temp_ss->string_length;
6de9cd9a
DN
2569 n = loop->temp_ss->data.temp.dimen;
2570 memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
2571 loop->temp_ss->type = GFC_SS_SECTION;
2572 loop->temp_ss->data.info.dimen = n;
40f20186 2573 gfc_trans_allocate_temp_array (loop, &loop->temp_ss->data.info, tmp);
6de9cd9a
DN
2574 }
2575
6de9cd9a
DN
2576 for (n = 0; n < loop->temp_dim; n++)
2577 loopspec[loop->order[n]] = NULL;
2578
2579 mpz_clear (i);
2580
2581 /* For array parameters we don't have loop variables, so don't calculate the
2582 translations. */
2583 if (loop->array_parameter)
2584 return;
2585
2586 /* Calculate the translation from loop variables to array indices. */
2587 for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
2588 {
e9cfef64 2589 if (ss->type != GFC_SS_SECTION && ss->type != GFC_SS_COMPONENT)
6de9cd9a
DN
2590 continue;
2591
2592 info = &ss->data.info;
2593
2594 for (n = 0; n < info->dimen; n++)
2595 {
2596 dim = info->dim[n];
2597
e9cfef64 2598 /* If we are specifying the range the delta is already set. */
6de9cd9a
DN
2599 if (loopspec[n] != ss)
2600 {
2601 /* Calculate the offset relative to the loop variable.
2602 First multiply by the stride. */
923ab88c
TS
2603 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type,
2604 loop->from[n], info->stride[n]));
6de9cd9a
DN
2605
2606 /* Then subtract this from our starting value. */
923ab88c
TS
2607 tmp = fold (build2 (MINUS_EXPR, gfc_array_index_type,
2608 info->start[n], tmp));
6de9cd9a
DN
2609
2610 info->delta[n] = gfc_evaluate_now (tmp, &loop->pre);
2611 }
2612 }
2613 }
2614}
2615
2616
2617/* Fills in an array descriptor, and returns the size of the array. The size
2618 will be a simple_val, ie a variable or a constant. Also calculates the
1f2959f0 2619 offset of the base. Returns the size of the array.
6de9cd9a
DN
2620 {
2621 stride = 1;
2622 offset = 0;
2623 for (n = 0; n < rank; n++)
2624 {
2625 a.lbound[n] = specified_lower_bound;
2626 offset = offset + a.lbond[n] * stride;
2627 size = 1 - lbound;
2628 a.ubound[n] = specified_upper_bound;
2629 a.stride[n] = stride;
2630 size = ubound + size; //size = ubound + 1 - lbound
2631 stride = stride * size;
2632 }
2633 return (stride);
2634 } */
2635/*GCC ARRAYS*/
2636
2637static tree
2638gfc_array_init_size (tree descriptor, int rank, tree * poffset,
2639 gfc_expr ** lower, gfc_expr ** upper,
2640 stmtblock_t * pblock)
2641{
2642 tree type;
2643 tree tmp;
2644 tree size;
2645 tree offset;
2646 tree stride;
2647 gfc_expr *ubound;
2648 gfc_se se;
2649 int n;
2650
2651 type = TREE_TYPE (descriptor);
2652
7ab92584
SB
2653 stride = gfc_index_one_node;
2654 offset = gfc_index_zero_node;
6de9cd9a
DN
2655
2656 /* Set the dtype. */
2657 tmp = gfc_conv_descriptor_dtype (descriptor);
40b026d8 2658 gfc_add_modify_expr (pblock, tmp, gfc_get_dtype (TREE_TYPE (descriptor)));
6de9cd9a
DN
2659
2660 for (n = 0; n < rank; n++)
2661 {
2662 /* We have 3 possibilities for determining the size of the array:
2663 lower == NULL => lbound = 1, ubound = upper[n]
2664 upper[n] = NULL => lbound = 1, ubound = lower[n]
2665 upper[n] != NULL => lbound = lower[n], ubound = upper[n] */
2666 ubound = upper[n];
2667
2668 /* Set lower bound. */
2669 gfc_init_se (&se, NULL);
2670 if (lower == NULL)
7ab92584 2671 se.expr = gfc_index_one_node;
6de9cd9a
DN
2672 else
2673 {
6e45f57b 2674 gcc_assert (lower[n]);
6de9cd9a
DN
2675 if (ubound)
2676 {
2677 gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
2678 gfc_add_block_to_block (pblock, &se.pre);
2679 }
2680 else
2681 {
7ab92584 2682 se.expr = gfc_index_one_node;
6de9cd9a
DN
2683 ubound = lower[n];
2684 }
2685 }
2686 tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
2687 gfc_add_modify_expr (pblock, tmp, se.expr);
2688
2689 /* Work out the offset for this component. */
923ab88c
TS
2690 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride));
2691 offset = fold (build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp));
6de9cd9a
DN
2692
2693 /* Start the calculation for the size of this dimension. */
923ab88c
TS
2694 size = build2 (MINUS_EXPR, gfc_array_index_type,
2695 gfc_index_one_node, se.expr);
6de9cd9a
DN
2696
2697 /* Set upper bound. */
2698 gfc_init_se (&se, NULL);
6e45f57b 2699 gcc_assert (ubound);
6de9cd9a
DN
2700 gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
2701 gfc_add_block_to_block (pblock, &se.pre);
2702
2703 tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
2704 gfc_add_modify_expr (pblock, tmp, se.expr);
2705
2706 /* Store the stride. */
2707 tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
2708 gfc_add_modify_expr (pblock, tmp, stride);
2709
2710 /* Calculate the size of this dimension. */
923ab88c 2711 size = fold (build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size));
6de9cd9a
DN
2712
2713 /* Multiply the stride by the number of elements in this dimension. */
923ab88c 2714 stride = fold (build2 (MULT_EXPR, gfc_array_index_type, stride, size));
6de9cd9a
DN
2715 stride = gfc_evaluate_now (stride, pblock);
2716 }
2717
2718 /* The stride is the number of elements in the array, so multiply by the
2719 size of an element to get the total size. */
2720 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
923ab88c 2721 size = fold (build2 (MULT_EXPR, gfc_array_index_type, stride, tmp));
6de9cd9a
DN
2722
2723 if (poffset != NULL)
2724 {
2725 offset = gfc_evaluate_now (offset, pblock);
2726 *poffset = offset;
2727 }
2728
2729 size = gfc_evaluate_now (size, pblock);
2730 return size;
2731}
2732
2733
1f2959f0 2734/* Initializes the descriptor and generates a call to _gfor_allocate. Does
6de9cd9a
DN
2735 the work for an ALLOCATE statement. */
2736/*GCC ARRAYS*/
2737
2738void
2739gfc_array_allocate (gfc_se * se, gfc_ref * ref, tree pstat)
2740{
2741 tree tmp;
2742 tree pointer;
2743 tree allocate;
2744 tree offset;
2745 tree size;
2746 gfc_expr **lower;
2747 gfc_expr **upper;
2748
2749 /* Figure out the size of the array. */
2750 switch (ref->u.ar.type)
2751 {
2752 case AR_ELEMENT:
2753 lower = NULL;
2754 upper = ref->u.ar.start;
2755 break;
2756
2757 case AR_FULL:
6e45f57b 2758 gcc_assert (ref->u.ar.as->type == AS_EXPLICIT);
6de9cd9a
DN
2759
2760 lower = ref->u.ar.as->lower;
2761 upper = ref->u.ar.as->upper;
2762 break;
2763
2764 case AR_SECTION:
2765 lower = ref->u.ar.start;
2766 upper = ref->u.ar.end;
2767 break;
2768
2769 default:
6e45f57b 2770 gcc_unreachable ();
6de9cd9a
DN
2771 break;
2772 }
2773
2774 size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
2775 lower, upper, &se->pre);
2776
2777 /* Allocate memory to store the data. */
2778 tmp = gfc_conv_descriptor_data (se->expr);
2779 pointer = gfc_build_addr_expr (NULL, tmp);
2780 pointer = gfc_evaluate_now (pointer, &se->pre);
2781
e2cad04b 2782 if (TYPE_PRECISION (gfc_array_index_type) == 32)
6de9cd9a 2783 allocate = gfor_fndecl_allocate;
e2cad04b 2784 else if (TYPE_PRECISION (gfc_array_index_type) == 64)
6de9cd9a
DN
2785 allocate = gfor_fndecl_allocate64;
2786 else
6e45f57b 2787 gcc_unreachable ();
6de9cd9a
DN
2788
2789 tmp = gfc_chainon_list (NULL_TREE, pointer);
2790 tmp = gfc_chainon_list (tmp, size);
2791 tmp = gfc_chainon_list (tmp, pstat);
2792 tmp = gfc_build_function_call (allocate, tmp);
2793 gfc_add_expr_to_block (&se->pre, tmp);
2794
2795 pointer = gfc_conv_descriptor_data (se->expr);
2796
2797 tmp = gfc_conv_descriptor_offset (se->expr);
2798 gfc_add_modify_expr (&se->pre, tmp, offset);
2799}
2800
2801
2802/* Deallocate an array variable. Also used when an allocated variable goes
2803 out of scope. */
2804/*GCC ARRAYS*/
2805
2806tree
2807gfc_array_deallocate (tree descriptor)
2808{
2809 tree var;
2810 tree tmp;
2811 stmtblock_t block;
2812
2813 gfc_start_block (&block);
2814 /* Get a pointer to the data. */
2815 tmp = gfc_conv_descriptor_data (descriptor);
2816 tmp = gfc_build_addr_expr (NULL, tmp);
2817 var = gfc_create_var (TREE_TYPE (tmp), "ptr");
2818 gfc_add_modify_expr (&block, var, tmp);
2819
2820 /* Parameter is the address of the data component. */
2821 tmp = gfc_chainon_list (NULL_TREE, var);
2822 tmp = gfc_chainon_list (tmp, integer_zero_node);
2823 tmp = gfc_build_function_call (gfor_fndecl_deallocate, tmp);
2824 gfc_add_expr_to_block (&block, tmp);
2825
2826 return gfc_finish_block (&block);
2827}
2828
2829
2830/* Create an array constructor from an initialization expression.
2831 We assume the frontend already did any expansions and conversions. */
2832
2833tree
2834gfc_conv_array_initializer (tree type, gfc_expr * expr)
2835{
2836 gfc_constructor *c;
2837 tree list;
2838 tree tmp;
2839 mpz_t maxval;
2840 gfc_se se;
2841 HOST_WIDE_INT hi;
2842 unsigned HOST_WIDE_INT lo;
2843 tree index, range;
2844
2845 list = NULL_TREE;
2846 switch (expr->expr_type)
2847 {
2848 case EXPR_CONSTANT:
2849 case EXPR_STRUCTURE:
2850 /* A single scalar or derived type value. Create an array with all
2851 elements equal to that value. */
2852 gfc_init_se (&se, NULL);
e9cfef64
PB
2853
2854 if (expr->expr_type == EXPR_CONSTANT)
2855 gfc_conv_constant (&se, expr);
2856 else
2857 gfc_conv_structure (&se, expr, 1);
6de9cd9a
DN
2858
2859 tmp = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
6e45f57b 2860 gcc_assert (tmp && INTEGER_CST_P (tmp));
6de9cd9a
DN
2861 hi = TREE_INT_CST_HIGH (tmp);
2862 lo = TREE_INT_CST_LOW (tmp);
2863 lo++;
2864 if (lo == 0)
2865 hi++;
2866 /* This will probably eat buckets of memory for large arrays. */
2867 while (hi != 0 || lo != 0)
2868 {
2869 list = tree_cons (NULL_TREE, se.expr, list);
2870 if (lo == 0)
2871 hi--;
2872 lo--;
2873 }
2874 break;
2875
2876 case EXPR_ARRAY:
2877 /* Create a list of all the elements. */
2878 for (c = expr->value.constructor; c; c = c->next)
2879 {
2880 if (c->iterator)
2881 {
2882 /* Problems occur when we get something like
2883 integer :: a(lots) = (/(i, i=1,lots)/) */
2884 /* TODO: Unexpanded array initializers. */
2885 internal_error
2886 ("Possible frontend bug: array constructor not expanded");
2887 }
2888 if (mpz_cmp_si (c->n.offset, 0) != 0)
2889 index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
2890 else
2891 index = NULL_TREE;
2892 mpz_init (maxval);
2893 if (mpz_cmp_si (c->repeat, 0) != 0)
2894 {
2895 tree tmp1, tmp2;
2896
2897 mpz_set (maxval, c->repeat);
2898 mpz_add (maxval, c->n.offset, maxval);
2899 mpz_sub_ui (maxval, maxval, 1);
2900 tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
2901 if (mpz_cmp_si (c->n.offset, 0) != 0)
2902 {
2903 mpz_add_ui (maxval, c->n.offset, 1);
2904 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
2905 }
2906 else
2907 tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
2908
923ab88c 2909 range = build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
6de9cd9a
DN
2910 }
2911 else
2912 range = NULL;
2913 mpz_clear (maxval);
2914
2915 gfc_init_se (&se, NULL);
2916 switch (c->expr->expr_type)
2917 {
2918 case EXPR_CONSTANT:
2919 gfc_conv_constant (&se, c->expr);
2920 if (range == NULL_TREE)
2921 list = tree_cons (index, se.expr, list);
2922 else
2923 {
2924 if (index != NULL_TREE)
2925 list = tree_cons (index, se.expr, list);
2926 list = tree_cons (range, se.expr, list);
2927 }
2928 break;
2929
2930 case EXPR_STRUCTURE:
2931 gfc_conv_structure (&se, c->expr, 1);
2932 list = tree_cons (index, se.expr, list);
2933 break;
2934
2935 default:
6e45f57b 2936 gcc_unreachable ();
6de9cd9a
DN
2937 }
2938 }
2939 /* We created the list in reverse order. */
2940 list = nreverse (list);
2941 break;
2942
2943 default:
6e45f57b 2944 gcc_unreachable ();
6de9cd9a
DN
2945 }
2946
2947 /* Create a constructor from the list of elements. */
2948 tmp = build1 (CONSTRUCTOR, type, list);
2949 TREE_CONSTANT (tmp) = 1;
2950 TREE_INVARIANT (tmp) = 1;
2951 return tmp;
2952}
2953
2954
2955/* Generate code to evaluate non-constant array bounds. Sets *poffset and
2956 returns the size (in elements) of the array. */
2957
2958static tree
2959gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
2960 stmtblock_t * pblock)
2961{
2962 gfc_array_spec *as;
2963 tree size;
2964 tree stride;
2965 tree offset;
2966 tree ubound;
2967 tree lbound;
2968 tree tmp;
2969 gfc_se se;
2970
2971 int dim;
2972
2973 as = sym->as;
2974
7ab92584
SB
2975 size = gfc_index_one_node;
2976 offset = gfc_index_zero_node;
6de9cd9a
DN
2977 for (dim = 0; dim < as->rank; dim++)
2978 {
2979 /* Evaluate non-constant array bound expressions. */
2980 lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
2981 if (as->lower[dim] && !INTEGER_CST_P (lbound))
2982 {
2983 gfc_init_se (&se, NULL);
2984 gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
2985 gfc_add_block_to_block (pblock, &se.pre);
2986 gfc_add_modify_expr (pblock, lbound, se.expr);
2987 }
2988 ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
2989 if (as->upper[dim] && !INTEGER_CST_P (ubound))
2990 {
2991 gfc_init_se (&se, NULL);
2992 gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
2993 gfc_add_block_to_block (pblock, &se.pre);
2994 gfc_add_modify_expr (pblock, ubound, se.expr);
2995 }
f7b529fa 2996 /* The offset of this dimension. offset = offset - lbound * stride. */
923ab88c
TS
2997 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type, lbound, size));
2998 offset = fold (build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp));
6de9cd9a
DN
2999
3000 /* The size of this dimension, and the stride of the next. */
3001 if (dim + 1 < as->rank)
3002 stride = GFC_TYPE_ARRAY_STRIDE (type, dim + 1);
3003 else
3004 stride = NULL_TREE;
3005
3006 if (ubound != NULL_TREE && !(stride && INTEGER_CST_P (stride)))
3007 {
3008 /* Calculate stride = size * (ubound + 1 - lbound). */
923ab88c
TS
3009 tmp = fold (build2 (MINUS_EXPR, gfc_array_index_type,
3010 gfc_index_one_node, lbound));
3011 tmp = fold (build2 (PLUS_EXPR, gfc_array_index_type, ubound, tmp));
3012 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type, size, tmp));
6de9cd9a
DN
3013 if (stride)
3014 gfc_add_modify_expr (pblock, stride, tmp);
3015 else
3016 stride = gfc_evaluate_now (tmp, pblock);
3017 }
3018
3019 size = stride;
3020 }
3021
3022 *poffset = offset;
3023 return size;
3024}
3025
3026
3027/* Generate code to initialize/allocate an array variable. */
3028
3029tree
3030gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
3031{
3032 stmtblock_t block;
3033 tree type;
3034 tree tmp;
3035 tree fndecl;
3036 tree size;
3037 tree offset;
6de9cd9a
DN
3038 bool onstack;
3039
6e45f57b 3040 gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
6de9cd9a
DN
3041
3042 /* Do nothing for USEd variables. */
3043 if (sym->attr.use_assoc)
3044 return fnbody;
3045
3046 type = TREE_TYPE (decl);
6e45f57b 3047 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a
DN
3048 onstack = TREE_CODE (type) != POINTER_TYPE;
3049
6de9cd9a
DN
3050 gfc_start_block (&block);
3051
3052 /* Evaluate character string length. */
3053 if (sym->ts.type == BT_CHARACTER
3054 && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3055 {
3056 gfc_trans_init_string_length (sym->ts.cl, &block);
3057
1a186ec5 3058 /* Emit a DECL_EXPR for this variable, which will cause the
13795658 3059 gimplifier to allocate storage, and all that good stuff. */
923ab88c 3060 tmp = build1 (DECL_EXPR, TREE_TYPE (decl), decl);
6de9cd9a
DN
3061 gfc_add_expr_to_block (&block, tmp);
3062 }
3063
3064 if (onstack)
3065 {
6de9cd9a
DN
3066 gfc_add_expr_to_block (&block, fnbody);
3067 return gfc_finish_block (&block);
3068 }
3069
3070 type = TREE_TYPE (type);
3071
6e45f57b
PB
3072 gcc_assert (!sym->attr.use_assoc);
3073 gcc_assert (!TREE_STATIC (decl));
cb9e4f55 3074 gcc_assert (!sym->module);
6de9cd9a
DN
3075
3076 if (sym->ts.type == BT_CHARACTER
3077 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3078 gfc_trans_init_string_length (sym->ts.cl, &block);
3079
3080 size = gfc_trans_array_bounds (type, sym, &offset, &block);
3081
3082 /* The size is the number of elements in the array, so multiply by the
3083 size of an element to get the total size. */
3084 tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
923ab88c 3085 size = fold (build2 (MULT_EXPR, gfc_array_index_type, size, tmp));
6de9cd9a
DN
3086
3087 /* Allocate memory to hold the data. */
3088 tmp = gfc_chainon_list (NULL_TREE, size);
3089
3090 if (gfc_index_integer_kind == 4)
3091 fndecl = gfor_fndecl_internal_malloc;
3092 else if (gfc_index_integer_kind == 8)
3093 fndecl = gfor_fndecl_internal_malloc64;
3094 else
6e45f57b 3095 gcc_unreachable ();
6de9cd9a
DN
3096 tmp = gfc_build_function_call (fndecl, tmp);
3097 tmp = fold (convert (TREE_TYPE (decl), tmp));
3098 gfc_add_modify_expr (&block, decl, tmp);
3099
3100 /* Set offset of the array. */
3101 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3102 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
3103
3104
3105 /* Automatic arrays should not have initializers. */
6e45f57b 3106 gcc_assert (!sym->value);
6de9cd9a
DN
3107
3108 gfc_add_expr_to_block (&block, fnbody);
3109
3110 /* Free the temporary. */
3111 tmp = convert (pvoid_type_node, decl);
3112 tmp = gfc_chainon_list (NULL_TREE, tmp);
3113 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
3114 gfc_add_expr_to_block (&block, tmp);
3115
3116 return gfc_finish_block (&block);
3117}
3118
3119
3120/* Generate entry and exit code for g77 calling convention arrays. */
3121
3122tree
3123gfc_trans_g77_array (gfc_symbol * sym, tree body)
3124{
3125 tree parm;
3126 tree type;
3127 locus loc;
3128 tree offset;
3129 tree tmp;
3130 stmtblock_t block;
3131
3132 gfc_get_backend_locus (&loc);
3133 gfc_set_backend_locus (&sym->declared_at);
3134
3135 /* Descriptor type. */
3136 parm = sym->backend_decl;
3137 type = TREE_TYPE (parm);
6e45f57b 3138 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a
DN
3139
3140 gfc_start_block (&block);
3141
3142 if (sym->ts.type == BT_CHARACTER
20c9dc8a 3143 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
6de9cd9a
DN
3144 gfc_trans_init_string_length (sym->ts.cl, &block);
3145
3146 /* Evaluate the bounds of the array. */
3147 gfc_trans_array_bounds (type, sym, &offset, &block);
3148
3149 /* Set the offset. */
3150 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3151 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
3152
1f2959f0 3153 /* Set the pointer itself if we aren't using the parameter directly. */
6de9cd9a
DN
3154 if (TREE_CODE (parm) != PARM_DECL)
3155 {
3156 tmp = convert (TREE_TYPE (parm), GFC_DECL_SAVED_DESCRIPTOR (parm));
3157 gfc_add_modify_expr (&block, parm, tmp);
3158 }
3159 tmp = gfc_finish_block (&block);
3160
3161 gfc_set_backend_locus (&loc);
3162
3163 gfc_start_block (&block);
3164 /* Add the initialization code to the start of the function. */
3165 gfc_add_expr_to_block (&block, tmp);
3166 gfc_add_expr_to_block (&block, body);
3167
3168 return gfc_finish_block (&block);
3169}
3170
3171
3172/* Modify the descriptor of an array parameter so that it has the
3173 correct lower bound. Also move the upper bound accordingly.
3174 If the array is not packed, it will be copied into a temporary.
3175 For each dimension we set the new lower and upper bounds. Then we copy the
3176 stride and calculate the offset for this dimension. We also work out
3177 what the stride of a packed array would be, and see it the two match.
3178 If the array need repacking, we set the stride to the values we just
3179 calculated, recalculate the offset and copy the array data.
3180 Code is also added to copy the data back at the end of the function.
3181 */
3182
3183tree
3184gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
3185{
3186 tree size;
3187 tree type;
3188 tree offset;
3189 locus loc;
3190 stmtblock_t block;
3191 stmtblock_t cleanup;
3192 tree lbound;
3193 tree ubound;
3194 tree dubound;
3195 tree dlbound;
3196 tree dumdesc;
3197 tree tmp;
3198 tree stmt;
3199 tree stride;
3200 tree stmt_packed;
3201 tree stmt_unpacked;
3202 tree partial;
3203 gfc_se se;
3204 int n;
3205 int checkparm;
3206 int no_repack;
3d79abbd 3207 bool optional_arg;
6de9cd9a 3208
fc90a8f2
PB
3209 /* Do nothing for pointer and allocatable arrays. */
3210 if (sym->attr.pointer || sym->attr.allocatable)
3211 return body;
3212
6de9cd9a
DN
3213 if (sym->attr.dummy && gfc_is_nodesc_array (sym))
3214 return gfc_trans_g77_array (sym, body);
3215
3216 gfc_get_backend_locus (&loc);
3217 gfc_set_backend_locus (&sym->declared_at);
3218
3219 /* Descriptor type. */
3220 type = TREE_TYPE (tmpdesc);
6e45f57b 3221 gcc_assert (GFC_ARRAY_TYPE_P (type));
6de9cd9a
DN
3222 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
3223 dumdesc = gfc_build_indirect_ref (dumdesc);
3224 gfc_start_block (&block);
3225
3226 if (sym->ts.type == BT_CHARACTER
20c9dc8a 3227 && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
6de9cd9a
DN
3228 gfc_trans_init_string_length (sym->ts.cl, &block);
3229
3230 checkparm = (sym->as->type == AS_EXPLICIT && flag_bounds_check);
3231
3232 no_repack = !(GFC_DECL_PACKED_ARRAY (tmpdesc)
3233 || GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc));
3234
3235 if (GFC_DECL_PARTIAL_PACKED_ARRAY (tmpdesc))
3236 {
3237 /* For non-constant shape arrays we only check if the first dimension
3238 is contiguous. Repacking higher dimensions wouldn't gain us
3239 anything as we still don't know the array stride. */
3240 partial = gfc_create_var (boolean_type_node, "partial");
3241 TREE_USED (partial) = 1;
3242 tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
923ab88c 3243 tmp = fold (build2 (EQ_EXPR, boolean_type_node, tmp, integer_one_node));
6de9cd9a
DN
3244 gfc_add_modify_expr (&block, partial, tmp);
3245 }
3246 else
3247 {
3248 partial = NULL_TREE;
3249 }
3250
3251 /* The naming of stmt_unpacked and stmt_packed may be counter-intuitive
3252 here, however I think it does the right thing. */
3253 if (no_repack)
3254 {
3255 /* Set the first stride. */
3256 stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
3257 stride = gfc_evaluate_now (stride, &block);
3258
923ab88c
TS
3259 tmp = build2 (EQ_EXPR, boolean_type_node, stride, integer_zero_node);
3260 tmp = build3 (COND_EXPR, gfc_array_index_type, tmp,
3261 gfc_index_one_node, stride);
6de9cd9a
DN
3262 stride = GFC_TYPE_ARRAY_STRIDE (type, 0);
3263 gfc_add_modify_expr (&block, stride, tmp);
3264
3265 /* Allow the user to disable array repacking. */
3266 stmt_unpacked = NULL_TREE;
3267 }
3268 else
3269 {
6e45f57b 3270 gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
1f2959f0 3271 /* A library call to repack the array if necessary. */
6de9cd9a
DN
3272 tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
3273 tmp = gfc_chainon_list (NULL_TREE, tmp);
3274 stmt_unpacked = gfc_build_function_call (gfor_fndecl_in_pack, tmp);
3275
7ab92584 3276 stride = gfc_index_one_node;
6de9cd9a
DN
3277 }
3278
3279 /* This is for the case where the array data is used directly without
3280 calling the repack function. */
3281 if (no_repack || partial != NULL_TREE)
3282 stmt_packed = gfc_conv_descriptor_data (dumdesc);
3283 else
3284 stmt_packed = NULL_TREE;
3285
3286 /* Assign the data pointer. */
3287 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
3288 {
3289 /* Don't repack unknown shape arrays when the first stride is 1. */
923ab88c
TS
3290 tmp = build3 (COND_EXPR, TREE_TYPE (stmt_packed), partial,
3291 stmt_packed, stmt_unpacked);
6de9cd9a
DN
3292 }
3293 else
3294 tmp = stmt_packed != NULL_TREE ? stmt_packed : stmt_unpacked;
7ab92584 3295 gfc_add_modify_expr (&block, tmpdesc, fold_convert (type, tmp));
6de9cd9a 3296
7ab92584
SB
3297 offset = gfc_index_zero_node;
3298 size = gfc_index_one_node;
6de9cd9a
DN
3299
3300 /* Evaluate the bounds of the array. */
3301 for (n = 0; n < sym->as->rank; n++)
3302 {
3303 if (checkparm || !sym->as->upper[n])
3304 {
3305 /* Get the bounds of the actual parameter. */
3306 dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
3307 dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
3308 }
3309 else
3310 {
3311 dubound = NULL_TREE;
3312 dlbound = NULL_TREE;
3313 }
3314
3315 lbound = GFC_TYPE_ARRAY_LBOUND (type, n);
3316 if (!INTEGER_CST_P (lbound))
3317 {
3318 gfc_init_se (&se, NULL);
3319 gfc_conv_expr_type (&se, sym->as->upper[n],
3320 gfc_array_index_type);
3321 gfc_add_block_to_block (&block, &se.pre);
3322 gfc_add_modify_expr (&block, lbound, se.expr);
3323 }
3324
3325 ubound = GFC_TYPE_ARRAY_UBOUND (type, n);
3326 /* Set the desired upper bound. */
3327 if (sym->as->upper[n])
3328 {
3329 /* We know what we want the upper bound to be. */
3330 if (!INTEGER_CST_P (ubound))
3331 {
3332 gfc_init_se (&se, NULL);
3333 gfc_conv_expr_type (&se, sym->as->upper[n],
3334 gfc_array_index_type);
3335 gfc_add_block_to_block (&block, &se.pre);
3336 gfc_add_modify_expr (&block, ubound, se.expr);
3337 }
3338
3339 /* Check the sizes match. */
3340 if (checkparm)
3341 {
3342 /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)). */
3343
923ab88c
TS
3344 tmp = fold (build2 (MINUS_EXPR, gfc_array_index_type,
3345 ubound, lbound));
3346 stride = build2 (MINUS_EXPR, gfc_array_index_type,
3347 dubound, dlbound);
3348 tmp = fold (build2 (NE_EXPR, gfc_array_index_type, tmp, stride));
6de9cd9a
DN
3349 gfc_trans_runtime_check (tmp, gfc_strconst_bounds, &block);
3350 }
3351 }
3352 else
3353 {
3354 /* For assumed shape arrays move the upper bound by the same amount
3355 as the lower bound. */
923ab88c
TS
3356 tmp = build2 (MINUS_EXPR, gfc_array_index_type, dubound, dlbound);
3357 tmp = fold (build2 (PLUS_EXPR, gfc_array_index_type, tmp, lbound));
6de9cd9a
DN
3358 gfc_add_modify_expr (&block, ubound, tmp);
3359 }
f7b529fa 3360 /* The offset of this dimension. offset = offset - lbound * stride. */
923ab88c
TS
3361 tmp = fold (build2 (MULT_EXPR, gfc_array_index_type, lbound, stride));
3362 offset = fold (build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp));
6de9cd9a
DN
3363
3364 /* The size of this dimension, and the stride of the next. */
3365 if (n + 1 < sym->as->rank)
3366 {
3367 stride = GFC_TYPE_ARRAY_STRIDE (type, n + 1);
3368
3369 if (no_repack || partial != NULL_TREE)
3370 {
3371 stmt_unpacked =
3372 gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
3373 }
3374
3375 /* Figure out the stride if not a known constant. */
3376 if (!INTEGER_CST_P (stride))
3377 {
3378 if (no_repack)
3379 stmt_packed = NULL_TREE;
3380 else
3381 {
3382 /* Calculate stride = size * (ubound + 1 - lbound). */
923ab88c
TS
3383 tmp = fold (build2 (MINUS_EXPR, gfc_array_index_type,
3384 gfc_index_one_node, lbound));
3385 tmp = fold (build2 (PLUS_EXPR, gfc_array_index_type,
3386 ubound, tmp));
3387 size = fold (build2 (MULT_EXPR, gfc_array_index_type,
3388 size, tmp));
6de9cd9a
DN
3389 stmt_packed = size;
3390 }
3391
3392 /* Assign the stride. */
3393 if (stmt_packed != NULL_TREE && stmt_unpacked != NULL_TREE)
923ab88c
TS
3394 tmp = build3 (COND_EXPR, gfc_array_index_type, partial,
3395 stmt_unpacked, stmt_packed);
6de9cd9a
DN
3396 else
3397 tmp = (stmt_packed != NULL_TREE) ? stmt_packed : stmt_unpacked;
3398 gfc_add_modify_expr (&block, stride, tmp);
3399 }
3400 }
3401 }
3402
3403 /* Set the offset. */
3404 if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
3405 gfc_add_modify_expr (&block, GFC_TYPE_ARRAY_OFFSET (type), offset);
3406
3407 stmt = gfc_finish_block (&block);
3408
3409 gfc_start_block (&block);
3410
3411 /* Only do the entry/initialization code if the arg is present. */
3412 dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
3d79abbd
PB
3413 optional_arg = sym->attr.optional || sym->ns->proc_name->attr.entry_master;
3414 if (optional_arg)
6de9cd9a
DN
3415 {
3416 tmp = gfc_conv_expr_present (sym);
923ab88c 3417 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a
DN
3418 }
3419 gfc_add_expr_to_block (&block, stmt);
3420
3421 /* Add the main function body. */
3422 gfc_add_expr_to_block (&block, body);
3423
3424 /* Cleanup code. */
3425 if (!no_repack)
3426 {
3427 gfc_start_block (&cleanup);
3428
3429 if (sym->attr.intent != INTENT_IN)
3430 {
3431 /* Copy the data back. */
3432 tmp = gfc_chainon_list (NULL_TREE, dumdesc);
3433 tmp = gfc_chainon_list (tmp, tmpdesc);
3434 tmp = gfc_build_function_call (gfor_fndecl_in_unpack, tmp);
3435 gfc_add_expr_to_block (&cleanup, tmp);
3436 }
3437
3438 /* Free the temporary. */
3439 tmp = gfc_chainon_list (NULL_TREE, tmpdesc);
3440 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
3441 gfc_add_expr_to_block (&cleanup, tmp);
3442
3443 stmt = gfc_finish_block (&cleanup);
3444
3445 /* Only do the cleanup if the array was repacked. */
3446 tmp = gfc_build_indirect_ref (dumdesc);
3447 tmp = gfc_conv_descriptor_data (tmp);
923ab88c
TS
3448 tmp = build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
3449 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a 3450
3d79abbd 3451 if (optional_arg)
6de9cd9a
DN
3452 {
3453 tmp = gfc_conv_expr_present (sym);
923ab88c 3454 stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a
DN
3455 }
3456 gfc_add_expr_to_block (&block, stmt);
3457 }
3458 /* We don't need to free any memory allocated by internal_pack as it will
3459 be freed at the end of the function by pop_context. */
3460 return gfc_finish_block (&block);
3461}
3462
3463
7ab92584
SB
3464/* Convert an array for passing as an actual parameter. Expressions and
3465 vector subscripts are evaluated and stored in a temporary, which is then
6de9cd9a
DN
3466 passed. For whole arrays the descriptor is passed. For array sections
3467 a modified copy of the descriptor is passed, but using the original data.
3468 Also used for array pointer assignments by setting se->direct_byref. */
3469
3470void
3471gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
3472{
3473 gfc_loopinfo loop;
3474 gfc_ss *secss;
3475 gfc_ss_info *info;
3476 int need_tmp;
3477 int n;
3478 tree tmp;
3479 tree desc;
3480 stmtblock_t block;
3481 tree start;
3482 tree offset;
3483 int full;
fc90a8f2 3484 gfc_ss *vss;
ca2940c3 3485 gfc_ref *ref;
6de9cd9a 3486
6e45f57b 3487 gcc_assert (ss != gfc_ss_terminator);
6de9cd9a
DN
3488
3489 /* TODO: Pass constant array constructors without a temporary. */
fc90a8f2
PB
3490 /* Special case things we know we can pass easily. */
3491 switch (expr->expr_type)
6de9cd9a 3492 {
fc90a8f2
PB
3493 case EXPR_VARIABLE:
3494 /* If we have a linear array section, we can pass it directly.
3495 Otherwise we need to copy it into a temporary. */
6de9cd9a
DN
3496
3497 /* Find the SS for the array section. */
3498 secss = ss;
3499 while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION)
3500 secss = secss->next;
3501
6e45f57b 3502 gcc_assert (secss != gfc_ss_terminator);
6de9cd9a
DN
3503
3504 need_tmp = 0;
3505 for (n = 0; n < secss->data.info.dimen; n++)
3506 {
3507 vss = secss->data.info.subscript[secss->data.info.dim[n]];
3508 if (vss && vss->type == GFC_SS_VECTOR)
3509 need_tmp = 1;
3510 }
3511
3512 info = &secss->data.info;
3513
3514 /* Get the descriptor for the array. */
3515 gfc_conv_ss_descriptor (&se->pre, secss, 0);
3516 desc = info->descriptor;
3517 if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
3518 {
3519 /* Create a new descriptor if the array doesn't have one. */
3520 full = 0;
3521 }
3522 else if (info->ref->u.ar.type == AR_FULL)
3523 full = 1;
3524 else if (se->direct_byref)
3525 full = 0;
3526 else
3527 {
ca2940c3
TS
3528 ref = info->ref;
3529 gcc_assert (ref->u.ar.type == AR_SECTION);
6de9cd9a
DN
3530
3531 full = 1;
ca2940c3 3532 for (n = 0; n < ref->u.ar.dimen; n++)
6de9cd9a
DN
3533 {
3534 /* Detect passing the full array as a section. This could do
3535 even more checking, but it doesn't seem worth it. */
ca2940c3
TS
3536 if (ref->u.ar.start[n]
3537 || ref->u.ar.end[n]
3538 || (ref->u.ar.stride[n]
3539 && !gfc_expr_is_one (ref->u.ar.stride[n], 0)))
6de9cd9a
DN
3540 {
3541 full = 0;
3542 break;
3543 }
3544 }
3545 }
ca2940c3
TS
3546
3547 /* Check for substring references. */
3548 ref = expr->ref;
3549 if (!need_tmp && ref && expr->ts.type == BT_CHARACTER)
3550 {
3551 while (ref->next)
3552 ref = ref->next;
3553 if (ref->type == REF_SUBSTRING)
3554 {
3555 /* In general character substrings need a copy. Character
3556 array strides are expressed as multiples of the element
3557 size (consistent with other array types), not in
3558 characters. */
3559 full = 0;
3560 need_tmp = 1;
3561 }
3562 }
3563
6de9cd9a
DN
3564 if (full)
3565 {
3566 if (se->direct_byref)
3567 {
3568 /* Copy the descriptor for pointer assignments. */
3569 gfc_add_modify_expr (&se->pre, se->expr, desc);
3570 }
3571 else if (se->want_pointer)
3572 {
3573 /* We pass full arrays directly. This means that pointers and
fc90a8f2
PB
3574 allocatable arrays should also work. */
3575 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
6de9cd9a
DN
3576 }
3577 else
3578 {
3579 se->expr = desc;
3580 }
ca2940c3 3581
20c9dc8a 3582 if (expr->ts.type == BT_CHARACTER)
ca2940c3
TS
3583 se->string_length = gfc_get_expr_charlen (expr);
3584
6de9cd9a
DN
3585 return;
3586 }
fc90a8f2
PB
3587 break;
3588
3589 case EXPR_FUNCTION:
3590 /* A transformational function return value will be a temporary
3591 array descriptor. We still need to go through the scalarizer
3592 to create the descriptor. Elemental functions ar handled as
e7dc5b4f 3593 arbitrary expressions, i.e. copy to a temporary. */
fc90a8f2
PB
3594 secss = ss;
3595 /* Look for the SS for this function. */
3596 while (secss != gfc_ss_terminator
3597 && (secss->type != GFC_SS_FUNCTION || secss->expr != expr))
3598 secss = secss->next;
3599
3600 if (se->direct_byref)
3601 {
6e45f57b 3602 gcc_assert (secss != gfc_ss_terminator);
fc90a8f2
PB
3603
3604 /* For pointer assignments pass the descriptor directly. */
3605 se->ss = secss;
3606 se->expr = gfc_build_addr_expr (NULL, se->expr);
3607 gfc_conv_expr (se, expr);
3608 return;
3609 }
3610
3611 if (secss == gfc_ss_terminator)
3612 {
3613 /* Elemental function. */
3614 need_tmp = 1;
3615 info = NULL;
3616 }
3617 else
3618 {
3619 /* Transformational function. */
3620 info = &secss->data.info;
3621 need_tmp = 0;
3622 }
3623 break;
3624
3625 default:
3626 /* Something complicated. Copy it into a temporary. */
6de9cd9a
DN
3627 need_tmp = 1;
3628 secss = NULL;
3629 info = NULL;
fc90a8f2 3630 break;
6de9cd9a
DN
3631 }
3632
fc90a8f2 3633
6de9cd9a
DN
3634 gfc_init_loopinfo (&loop);
3635
3636 /* Associate the SS with the loop. */
3637 gfc_add_ss_to_loop (&loop, ss);
3638
13413760 3639 /* Tell the scalarizer not to bother creating loop variables, etc. */
6de9cd9a
DN
3640 if (!need_tmp)
3641 loop.array_parameter = 1;
3642 else
6e45f57b 3643 gcc_assert (se->want_pointer && !se->direct_byref);
6de9cd9a
DN
3644
3645 /* Setup the scalarizing loops and bounds. */
3646 gfc_conv_ss_startstride (&loop);
3647
3648 if (need_tmp)
3649 {
3650 /* Tell the scalarizer to make a temporary. */
3651 loop.temp_ss = gfc_get_ss ();
3652 loop.temp_ss->type = GFC_SS_TEMP;
3653 loop.temp_ss->next = gfc_ss_terminator;
3654 loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
ca2940c3 3655 /* ... which can hold our string, if present. */
20c9dc8a 3656 if (expr->ts.type == BT_CHARACTER)
40f20186 3657 se->string_length = loop.temp_ss->string_length
20c9dc8a
TS
3658 = TYPE_SIZE_UNIT (loop.temp_ss->data.temp.type);
3659 else
40f20186 3660 loop.temp_ss->string_length = NULL;
6de9cd9a
DN
3661 loop.temp_ss->data.temp.dimen = loop.dimen;
3662 gfc_add_ss_to_loop (&loop, loop.temp_ss);
3663 }
3664
3665 gfc_conv_loop_setup (&loop);
3666
3667 if (need_tmp)
3668 {
3669 /* Copy into a temporary and pass that. We don't need to copy the data
3670 back because expressions and vector subscripts must be INTENT_IN. */
3671 /* TODO: Optimize passing function return values. */
3672 gfc_se lse;
3673 gfc_se rse;
3674
3675 /* Start the copying loops. */
3676 gfc_mark_ss_chain_used (loop.temp_ss, 1);
3677 gfc_mark_ss_chain_used (ss, 1);
3678 gfc_start_scalarized_body (&loop, &block);
3679
3680 /* Copy each data element. */
3681 gfc_init_se (&lse, NULL);
3682 gfc_copy_loopinfo_to_se (&lse, &loop);
3683 gfc_init_se (&rse, NULL);
3684 gfc_copy_loopinfo_to_se (&rse, &loop);
3685
3686 lse.ss = loop.temp_ss;
3687 rse.ss = ss;
3688
3689 gfc_conv_scalarized_array_ref (&lse, NULL);
3690 gfc_conv_expr_val (&rse, expr);
3691
3692 gfc_add_block_to_block (&block, &rse.pre);
3693 gfc_add_block_to_block (&block, &lse.pre);
3694
3695 gfc_add_modify_expr (&block, lse.expr, rse.expr);
3696
3697 /* Finish the copying loops. */
3698 gfc_trans_scalarizing_loops (&loop, &block);
3699
3700 /* Set the first stride component to zero to indicate a temporary. */
3701 desc = loop.temp_ss->data.info.descriptor;
3702 tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[0]);
7ab92584 3703 gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
6de9cd9a 3704
6e45f57b 3705 gcc_assert (is_gimple_lvalue (desc));
6de9cd9a
DN
3706 se->expr = gfc_build_addr_expr (NULL, desc);
3707 }
fc90a8f2
PB
3708 else if (expr->expr_type == EXPR_FUNCTION)
3709 {
3710 desc = info->descriptor;
3711
3712 if (se->want_pointer)
3713 se->expr = gfc_build_addr_expr (NULL_TREE, desc);
3714 else
3715 se->expr = desc;
3716
3717 if (expr->ts.type == BT_CHARACTER)
3718 se->string_length = expr->symtree->n.sym->ts.cl->backend_decl;
3719 }
6de9cd9a
DN
3720 else
3721 {
fc90a8f2
PB
3722 /* We pass sections without copying to a temporary. Make a new
3723 descriptor and point it at the section we want. The loop variable
3724 limits will be the limits of the section.
3725 A function may decide to repack the array to speed up access, but
3726 we're not bothered about that here. */
6de9cd9a
DN
3727 int dim;
3728 tree parm;
3729 tree parmtype;
3730 tree stride;
3731 tree from;
3732 tree to;
3733 tree base;
3734
fc90a8f2 3735 /* Set the string_length for a character array. */
20c9dc8a 3736 if (expr->ts.type == BT_CHARACTER)
ca2940c3 3737 se->string_length = gfc_get_expr_charlen (expr);
20c9dc8a 3738
6de9cd9a 3739 desc = info->descriptor;
6e45f57b 3740 gcc_assert (secss && secss != gfc_ss_terminator);
6de9cd9a
DN
3741 if (se->direct_byref)
3742 {
3743 /* For pointer assignments we fill in the destination. */
3744 parm = se->expr;
3745 parmtype = TREE_TYPE (parm);
3746 }
3747 else
3748 {
3749 /* Otherwise make a new one. */
3750 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3751 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
3752 loop.from, loop.to, 0);
3753 parm = gfc_create_var (parmtype, "parm");
3754 }
3755
7ab92584 3756 offset = gfc_index_zero_node;
6de9cd9a
DN
3757 dim = 0;
3758
3759 /* The following can be somewhat confusing. We have two
3760 descriptors, a new one and the original array.
3761 {parm, parmtype, dim} refer to the new one.
3762 {desc, type, n, secss, loop} refer to the original, which maybe
3763 a descriptorless array.
e7dc5b4f 3764 The bounds of the scalarization are the bounds of the section.
6de9cd9a
DN
3765 We don't have to worry about numeric overflows when calculating
3766 the offsets because all elements are within the array data. */
3767
3768 /* Set the dtype. */
3769 tmp = gfc_conv_descriptor_dtype (parm);
40b026d8 3770 gfc_add_modify_expr (&loop.pre, tmp, gfc_get_dtype (parmtype));
6de9cd9a
DN
3771
3772 if (se->direct_byref)
7ab92584 3773 base = gfc_index_zero_node;
6de9cd9a
DN
3774 else
3775 base = NULL_TREE;
3776
3777 for (n = 0; n < info->ref->u.ar.dimen; n++)
3778 {
3779 stride = gfc_conv_array_stride (desc, n);
3780
3781 /* Work out the offset. */
3782 if (info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
3783 {
6e45f57b 3784 gcc_assert (info->subscript[n]
6de9cd9a
DN
3785 && info->subscript[n]->type == GFC_SS_SCALAR);
3786 start = info->subscript[n]->data.scalar.expr;
3787 }
3788 else
3789 {
3790 /* Check we haven't somehow got out of sync. */
6e45f57b 3791 gcc_assert (info->dim[dim] == n);
6de9cd9a
DN
3792
3793 /* Evaluate and remember the start of the section. */
3794 start = info->start[dim];
3795 stride = gfc_evaluate_now (stride, &loop.pre);
3796 }
3797
3798 tmp = gfc_conv_array_lbound (desc, n);
923ab88c 3799 tmp = fold (build2 (MINUS_EXPR, TREE_TYPE (tmp), start, tmp));
6de9cd9a 3800
923ab88c
TS
3801 tmp = fold (build2 (MULT_EXPR, TREE_TYPE (tmp), tmp, stride));
3802 offset = fold (build2 (PLUS_EXPR, TREE_TYPE (tmp), offset, tmp));
6de9cd9a
DN
3803
3804 if (info->ref->u.ar.dimen_type[n] == DIMEN_ELEMENT)
3805 {
3806 /* For elemental dimensions, we only need the offset. */
3807 continue;
3808 }
3809
3810 /* Vector subscripts need copying and are handled elsewhere. */
6e45f57b 3811 gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE);
6de9cd9a
DN
3812
3813 /* Set the new lower bound. */
3814 from = loop.from[dim];
3815 to = loop.to[dim];
3816 if (!integer_onep (from))
3817 {
3818 /* Make sure the new section starts at 1. */
923ab88c 3819 tmp = fold (build2 (MINUS_EXPR, gfc_array_index_type,
7ab92584 3820 gfc_index_one_node, from));
923ab88c 3821 to = fold (build2 (PLUS_EXPR, gfc_array_index_type, to, tmp));
7ab92584 3822 from = gfc_index_one_node;
6de9cd9a
DN
3823 }
3824 tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
3825 gfc_add_modify_expr (&loop.pre, tmp, from);
3826
3827 /* Set the new upper bound. */
3828 tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
3829 gfc_add_modify_expr (&loop.pre, tmp, to);
3830
3831 /* Multiply the stride by the section stride to get the
3832 total stride. */
923ab88c
TS
3833 stride = fold (build2 (MULT_EXPR, gfc_array_index_type,
3834 stride, info->stride[dim]));
6de9cd9a
DN
3835
3836 if (se->direct_byref)
923ab88c
TS
3837 base = fold (build2 (MINUS_EXPR, TREE_TYPE (base),
3838 base, stride));
6de9cd9a
DN
3839
3840 /* Store the new stride. */
3841 tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
3842 gfc_add_modify_expr (&loop.pre, tmp, stride);
3843
3844 dim++;
3845 }
3846
3847 /* Point the data pointer at the first element in the section. */
3848 tmp = gfc_conv_array_data (desc);
3849 tmp = gfc_build_indirect_ref (tmp);
3850 tmp = gfc_build_array_ref (tmp, offset);
3851 offset = gfc_build_addr_expr (gfc_array_dataptr_type (desc), tmp);
3852
3853 tmp = gfc_conv_descriptor_data (parm);
7ab92584
SB
3854 gfc_add_modify_expr (&loop.pre, tmp,
3855 fold_convert (TREE_TYPE (tmp), offset));
6de9cd9a
DN
3856
3857 if (se->direct_byref)
3858 {
3859 /* Set the offset. */
3860 tmp = gfc_conv_descriptor_offset (parm);
3861 gfc_add_modify_expr (&loop.pre, tmp, base);
3862 }
3863 else
3864 {
3865 /* Only the callee knows what the correct offset it, so just set
3866 it to zero here. */
3867 tmp = gfc_conv_descriptor_offset (parm);
3868 gfc_add_modify_expr (&loop.pre, tmp, gfc_index_zero_node);
3869 }
3870
3871 if (!se->direct_byref)
3872 {
3873 /* Get a pointer to the new descriptor. */
3874 if (se->want_pointer)
3875 se->expr = gfc_build_addr_expr (NULL, parm);
3876 else
3877 se->expr = parm;
3878 }
3879 }
3880
3881 gfc_add_block_to_block (&se->pre, &loop.pre);
3882 gfc_add_block_to_block (&se->post, &loop.post);
3883
3884 /* Cleanup the scalarizer. */
3885 gfc_cleanup_loop (&loop);
3886}
3887
3888
3889/* Convert an array for passing as an actual parameter. */
3890/* TODO: Optimize passing g77 arrays. */
3891
3892void
3893gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77)
3894{
3895 tree ptr;
3896 tree desc;
3897 tree tmp;
3898 tree stmt;
3899 gfc_symbol *sym;
3900 stmtblock_t block;
3901
3902 /* Passing address of the array if it is not pointer or assumed-shape. */
3903 if (expr->expr_type == EXPR_VARIABLE
3904 && expr->ref->u.ar.type == AR_FULL && g77)
3905 {
3906 sym = expr->symtree->n.sym;
3907 tmp = gfc_get_symbol_decl (sym);
20c9dc8a
TS
3908 if (sym->ts.type == BT_CHARACTER)
3909 se->string_length = sym->ts.cl->backend_decl;
6de9cd9a
DN
3910 if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE
3911 && !sym->attr.allocatable)
3912 {
346d5977 3913 /* Some variables are declared directly, others are declared as
841b0c1f
PB
3914 pointers and allocated on the heap. */
3915 if (sym->attr.dummy || POINTER_TYPE_P (TREE_TYPE (tmp)))
3916 se->expr = tmp;
6de9cd9a 3917 else
841b0c1f 3918 se->expr = gfc_build_addr_expr (NULL, tmp);
6de9cd9a
DN
3919 return;
3920 }
3921 if (sym->attr.allocatable)
3922 {
3923 se->expr = gfc_conv_array_data (tmp);
3924 return;
3925 }
3926 }
3927
3928 se->want_pointer = 1;
3929 gfc_conv_expr_descriptor (se, expr, ss);
3930
3931 if (g77)
3932 {
3933 desc = se->expr;
3934 /* Repack the array. */
3935 tmp = gfc_chainon_list (NULL_TREE, desc);
3936 ptr = gfc_build_function_call (gfor_fndecl_in_pack, tmp);
3937 ptr = gfc_evaluate_now (ptr, &se->pre);
3938 se->expr = ptr;
3939
3940 gfc_start_block (&block);
3941
3942 /* Copy the data back. */
3943 tmp = gfc_chainon_list (NULL_TREE, desc);
3944 tmp = gfc_chainon_list (tmp, ptr);
3945 tmp = gfc_build_function_call (gfor_fndecl_in_unpack, tmp);
3946 gfc_add_expr_to_block (&block, tmp);
3947
3948 /* Free the temporary. */
3949 tmp = convert (pvoid_type_node, ptr);
3950 tmp = gfc_chainon_list (NULL_TREE, tmp);
3951 tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
3952 gfc_add_expr_to_block (&block, tmp);
3953
3954 stmt = gfc_finish_block (&block);
3955
3956 gfc_init_block (&block);
3957 /* Only if it was repacked. This code needs to be executed before the
3958 loop cleanup code. */
3959 tmp = gfc_build_indirect_ref (desc);
3960 tmp = gfc_conv_array_data (tmp);
923ab88c
TS
3961 tmp = build2 (NE_EXPR, boolean_type_node, ptr, tmp);
3962 tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
6de9cd9a
DN
3963
3964 gfc_add_expr_to_block (&block, tmp);
3965 gfc_add_block_to_block (&block, &se->post);
3966
3967 gfc_init_block (&se->post);
3968 gfc_add_block_to_block (&se->post, &block);
3969 }
3970}
3971
3972
3973/* NULLIFY an allocated/pointer array on function entry, free it on exit. */
3974
3975tree
3976gfc_trans_deferred_array (gfc_symbol * sym, tree body)
3977{
3978 tree type;
3979 tree tmp;
3980 tree descriptor;
3981 tree deallocate;
3982 stmtblock_t block;
3983 stmtblock_t fnblock;
3984 locus loc;
3985
3986 /* Make sure the frontend gets these right. */
3987 if (!(sym->attr.pointer || sym->attr.allocatable))
3988 fatal_error
3989 ("Possible frontend bug: Deferred array size without pointer or allocatable attribute.");
3990
3991 gfc_init_block (&fnblock);
3992
6e45f57b 3993 gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL);
6de9cd9a
DN
3994 if (sym->ts.type == BT_CHARACTER
3995 && !INTEGER_CST_P (sym->ts.cl->backend_decl))
3996 gfc_trans_init_string_length (sym->ts.cl, &fnblock);
3997
2b58638b
PB
3998 /* Parameter and use associated variables don't need anything special. */
3999 if (sym->attr.dummy || sym->attr.use_assoc)
6de9cd9a
DN
4000 {
4001 gfc_add_expr_to_block (&fnblock, body);
4002
4003 return gfc_finish_block (&fnblock);
4004 }
4005
4006 gfc_get_backend_locus (&loc);
4007 gfc_set_backend_locus (&sym->declared_at);
4008 descriptor = sym->backend_decl;
4009
4010 if (TREE_STATIC (descriptor))
4011 {
4012 /* SAVEd variables are not freed on exit. */
4013 gfc_trans_static_array_pointer (sym);
4014 return body;
4015 }
4016
4017 /* Get the descriptor type. */
4018 type = TREE_TYPE (sym->backend_decl);
6e45f57b 4019 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
6de9cd9a
DN
4020
4021 /* NULLIFY the data pointer. */
4022 tmp = gfc_conv_descriptor_data (descriptor);
7ab92584
SB
4023 gfc_add_modify_expr (&fnblock, tmp,
4024 convert (TREE_TYPE (tmp), integer_zero_node));
6de9cd9a
DN
4025
4026 gfc_add_expr_to_block (&fnblock, body);
4027
4028 gfc_set_backend_locus (&loc);
4029 /* Allocatable arrays need to be freed when they go out of scope. */
4030 if (sym->attr.allocatable)
4031 {
4032 gfc_start_block (&block);
4033
4034 /* Deallocate if still allocated at the end of the procedure. */
4035 deallocate = gfc_array_deallocate (descriptor);
4036
4037 tmp = gfc_conv_descriptor_data (descriptor);
923ab88c
TS
4038 tmp = build2 (NE_EXPR, boolean_type_node, tmp, integer_zero_node);
4039 tmp = build3_v (COND_EXPR, tmp, deallocate, build_empty_stmt ());
6de9cd9a
DN
4040 gfc_add_expr_to_block (&block, tmp);
4041
4042 tmp = gfc_finish_block (&block);
4043 gfc_add_expr_to_block (&fnblock, tmp);
4044 }
4045
4046 return gfc_finish_block (&fnblock);
4047}
4048
4049/************ Expression Walking Functions ******************/
4050
4051/* Walk a variable reference.
4052
4053 Possible extension - multiple component subscripts.
4054 x(:,:) = foo%a(:)%b(:)
4055 Transforms to
4056 forall (i=..., j=...)
4057 x(i,j) = foo%a(j)%b(i)
4058 end forall
4059 This adds a fair amout of complexity because you need to deal with more
4060 than one ref. Maybe handle in a similar manner to vector subscripts.
4061 Maybe not worth the effort. */
4062
4063
4064static gfc_ss *
4065gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
4066{
4067 gfc_ref *ref;
4068 gfc_array_ref *ar;
4069 gfc_ss *newss;
4070 gfc_ss *head;
4071 int n;
4072
4073 for (ref = expr->ref; ref; ref = ref->next)
4074 {
4075 /* We're only interested in array sections. */
4076 if (ref->type != REF_ARRAY)
4077 continue;
4078
4079 ar = &ref->u.ar;
4080 switch (ar->type)
4081 {
4082 case AR_ELEMENT:
4083 /* TODO: Take elemental array references out of scalarization
4084 loop. */
4085 break;
4086
4087 case AR_FULL:
4088 newss = gfc_get_ss ();
4089 newss->type = GFC_SS_SECTION;
4090 newss->expr = expr;
4091 newss->next = ss;
4092 newss->data.info.dimen = ar->as->rank;
4093 newss->data.info.ref = ref;
4094
4095 /* Make sure array is the same as array(:,:), this way
4096 we don't need to special case all the time. */
4097 ar->dimen = ar->as->rank;
4098 for (n = 0; n < ar->dimen; n++)
4099 {
4100 newss->data.info.dim[n] = n;
4101 ar->dimen_type[n] = DIMEN_RANGE;
4102
6e45f57b
PB
4103 gcc_assert (ar->start[n] == NULL);
4104 gcc_assert (ar->end[n] == NULL);
4105 gcc_assert (ar->stride[n] == NULL);
6de9cd9a
DN
4106 }
4107 return newss;
4108
4109 case AR_SECTION:
4110 newss = gfc_get_ss ();
4111 newss->type = GFC_SS_SECTION;
4112 newss->expr = expr;
4113 newss->next = ss;
4114 newss->data.info.dimen = 0;
4115 newss->data.info.ref = ref;
4116
4117 head = newss;
4118
4119 /* We add SS chains for all the subscripts in the section. */
4120 for (n = 0; n < ar->dimen; n++)
4121 {
4122 gfc_ss *indexss;
4123
4124 switch (ar->dimen_type[n])
4125 {
4126 case DIMEN_ELEMENT:
4127 /* Add SS for elemental (scalar) subscripts. */
6e45f57b 4128 gcc_assert (ar->start[n]);
6de9cd9a
DN
4129 indexss = gfc_get_ss ();
4130 indexss->type = GFC_SS_SCALAR;
4131 indexss->expr = ar->start[n];
4132 indexss->next = gfc_ss_terminator;
4133 indexss->loop_chain = gfc_ss_terminator;
4134 newss->data.info.subscript[n] = indexss;
4135 break;
4136
4137 case DIMEN_RANGE:
4138 /* We don't add anything for sections, just remember this
4139 dimension for later. */
4140 newss->data.info.dim[newss->data.info.dimen] = n;
4141 newss->data.info.dimen++;
4142 break;
4143
4144 case DIMEN_VECTOR:
4145 /* Get a SS for the vector. This will not be added to the
4146 chain directly. */
4147 indexss = gfc_walk_expr (ar->start[n]);
4148 if (indexss == gfc_ss_terminator)
4149 internal_error ("scalar vector subscript???");
4150
4151 /* We currently only handle really simple vector
4152 subscripts. */
4153 if (indexss->next != gfc_ss_terminator)
4154 gfc_todo_error ("vector subscript expressions");
4155 indexss->loop_chain = gfc_ss_terminator;
4156
4157 /* Mark this as a vector subscript. We don't add this
4158 directly into the chain, but as a subscript of the
4159 existing SS for this term. */
4160 indexss->type = GFC_SS_VECTOR;
4161 newss->data.info.subscript[n] = indexss;
4162 /* Also remember this dimension. */
4163 newss->data.info.dim[newss->data.info.dimen] = n;
4164 newss->data.info.dimen++;
4165 break;
4166
4167 default:
4168 /* We should know what sort of section it is by now. */
6e45f57b 4169 gcc_unreachable ();
6de9cd9a
DN
4170 }
4171 }
4172 /* We should have at least one non-elemental dimension. */
6e45f57b 4173 gcc_assert (newss->data.info.dimen > 0);
6de9cd9a
DN
4174 return head;
4175 break;
4176
4177 default:
4178 /* We should know what sort of section it is by now. */
6e45f57b 4179 gcc_unreachable ();
6de9cd9a
DN
4180 }
4181
4182 }
4183 return ss;
4184}
4185
4186
4187/* Walk an expression operator. If only one operand of a binary expression is
4188 scalar, we must also add the scalar term to the SS chain. */
4189
4190static gfc_ss *
4191gfc_walk_op_expr (gfc_ss * ss, gfc_expr * expr)
4192{
4193 gfc_ss *head;
4194 gfc_ss *head2;
4195 gfc_ss *newss;
4196
58b03ab2
TS
4197 head = gfc_walk_subexpr (ss, expr->value.op.op1);
4198 if (expr->value.op.op2 == NULL)
6de9cd9a
DN
4199 head2 = head;
4200 else
58b03ab2 4201 head2 = gfc_walk_subexpr (head, expr->value.op.op2);
6de9cd9a
DN
4202
4203 /* All operands are scalar. Pass back and let the caller deal with it. */
4204 if (head2 == ss)
4205 return head2;
4206
f7b529fa 4207 /* All operands require scalarization. */
58b03ab2 4208 if (head != ss && (expr->value.op.op2 == NULL || head2 != head))
6de9cd9a
DN
4209 return head2;
4210
4211 /* One of the operands needs scalarization, the other is scalar.
4212 Create a gfc_ss for the scalar expression. */
4213 newss = gfc_get_ss ();
4214 newss->type = GFC_SS_SCALAR;
4215 if (head == ss)
4216 {
4217 /* First operand is scalar. We build the chain in reverse order, so
4218 add the scarar SS after the second operand. */
4219 head = head2;
4220 while (head && head->next != ss)
4221 head = head->next;
4222 /* Check we haven't somehow broken the chain. */
6e45f57b 4223 gcc_assert (head);
6de9cd9a
DN
4224 newss->next = ss;
4225 head->next = newss;
58b03ab2 4226 newss->expr = expr->value.op.op1;
6de9cd9a
DN
4227 }
4228 else /* head2 == head */
4229 {
6e45f57b 4230 gcc_assert (head2 == head);
6de9cd9a
DN
4231 /* Second operand is scalar. */
4232 newss->next = head2;
4233 head2 = newss;
58b03ab2 4234 newss->expr = expr->value.op.op2;
6de9cd9a
DN
4235 }
4236
4237 return head2;
4238}
4239
4240
4241/* Reverse a SS chain. */
4242
4243static gfc_ss *
4244gfc_reverse_ss (gfc_ss * ss)
4245{
4246 gfc_ss *next;
4247 gfc_ss *head;
4248
6e45f57b 4249 gcc_assert (ss != NULL);
6de9cd9a
DN
4250
4251 head = gfc_ss_terminator;
4252 while (ss != gfc_ss_terminator)
4253 {
4254 next = ss->next;
6e45f57b
PB
4255 /* Check we didn't somehow break the chain. */
4256 gcc_assert (next != NULL);
6de9cd9a
DN
4257 ss->next = head;
4258 head = ss;
4259 ss = next;
4260 }
4261
4262 return (head);
4263}
4264
4265
4266/* Walk the arguments of an elemental function. */
4267
4268gfc_ss *
4269gfc_walk_elemental_function_args (gfc_ss * ss, gfc_expr * expr,
4270 gfc_ss_type type)
4271{
4272 gfc_actual_arglist *arg;
4273 int scalar;
4274 gfc_ss *head;
4275 gfc_ss *tail;
4276 gfc_ss *newss;
4277
4278 head = gfc_ss_terminator;
4279 tail = NULL;
4280 scalar = 1;
4281 for (arg = expr->value.function.actual; arg; arg = arg->next)
4282 {
4283 if (!arg->expr)
4284 continue;
4285
4286 newss = gfc_walk_subexpr (head, arg->expr);
4287 if (newss == head)
4288 {
1f2959f0 4289 /* Scalar argument. */
6de9cd9a
DN
4290 newss = gfc_get_ss ();
4291 newss->type = type;
4292 newss->expr = arg->expr;
4293 newss->next = head;
4294 }
4295 else
4296 scalar = 0;
4297
4298 head = newss;
4299 if (!tail)
4300 {
4301 tail = head;
4302 while (tail->next != gfc_ss_terminator)
4303 tail = tail->next;
4304 }
4305 }
4306
4307 if (scalar)
4308 {
4309 /* If all the arguments are scalar we don't need the argument SS. */
4310 gfc_free_ss_chain (head);
4311 /* Pass it back. */
4312 return ss;
4313 }
4314
4315 /* Add it onto the existing chain. */
4316 tail->next = ss;
4317 return head;
4318}
4319
4320
4321/* Walk a function call. Scalar functions are passed back, and taken out of
4322 scalarization loops. For elemental functions we walk their arguments.
4323 The result of functions returning arrays is stored in a temporary outside
4324 the loop, so that the function is only called once. Hence we do not need
4325 to walk their arguments. */
4326
4327static gfc_ss *
4328gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
4329{
4330 gfc_ss *newss;
4331 gfc_intrinsic_sym *isym;
4332 gfc_symbol *sym;
4333
4334 isym = expr->value.function.isym;
4335
13413760 4336 /* Handle intrinsic functions separately. */
6de9cd9a
DN
4337 if (isym)
4338 return gfc_walk_intrinsic_function (ss, expr, isym);
4339
4340 sym = expr->value.function.esym;
4341 if (!sym)
4342 sym = expr->symtree->n.sym;
4343
4344 /* A function that returns arrays. */
4345 if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
4346 {
4347 newss = gfc_get_ss ();
4348 newss->type = GFC_SS_FUNCTION;
4349 newss->expr = expr;
4350 newss->next = ss;
4351 newss->data.info.dimen = expr->rank;
4352 return newss;
4353 }
4354
4355 /* Walk the parameters of an elemental function. For now we always pass
4356 by reference. */
4357 if (sym->attr.elemental)
4358 return gfc_walk_elemental_function_args (ss, expr, GFC_SS_REFERENCE);
4359
e7dc5b4f 4360 /* Scalar functions are OK as these are evaluated outside the scalarization
6de9cd9a
DN
4361 loop. Pass back and let the caller deal with it. */
4362 return ss;
4363}
4364
4365
4366/* An array temporary is constructed for array constructors. */
4367
4368static gfc_ss *
4369gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
4370{
4371 gfc_ss *newss;
4372 int n;
4373
4374 newss = gfc_get_ss ();
4375 newss->type = GFC_SS_CONSTRUCTOR;
4376 newss->expr = expr;
4377 newss->next = ss;
4378 newss->data.info.dimen = expr->rank;
4379 for (n = 0; n < expr->rank; n++)
4380 newss->data.info.dim[n] = n;
4381
4382 return newss;
4383}
4384
4385
1f2959f0 4386/* Walk an expression. Add walked expressions to the head of the SS chain.
6de9cd9a
DN
4387 A wholy scalar expression will not be added. */
4388
4389static gfc_ss *
4390gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
4391{
4392 gfc_ss *head;
4393
4394 switch (expr->expr_type)
4395 {
4396 case EXPR_VARIABLE:
4397 head = gfc_walk_variable_expr (ss, expr);
4398 return head;
4399
4400 case EXPR_OP:
4401 head = gfc_walk_op_expr (ss, expr);
4402 return head;
4403
4404 case EXPR_FUNCTION:
4405 head = gfc_walk_function_expr (ss, expr);
4406 return head;
4407
4408 case EXPR_CONSTANT:
4409 case EXPR_NULL:
4410 case EXPR_STRUCTURE:
4411 /* Pass back and let the caller deal with it. */
4412 break;
4413
4414 case EXPR_ARRAY:
4415 head = gfc_walk_array_constructor (ss, expr);
4416 return head;
4417
4418 case EXPR_SUBSTRING:
4419 /* Pass back and let the caller deal with it. */
4420 break;
4421
4422 default:
4423 internal_error ("bad expression type during walk (%d)",
4424 expr->expr_type);
4425 }
4426 return ss;
4427}
4428
4429
4430/* Entry point for expression walking.
4431 A return value equal to the passed chain means this is
4432 a scalar expression. It is up to the caller to take whatever action is
1f2959f0 4433 necessary to translate these. */
6de9cd9a
DN
4434
4435gfc_ss *
4436gfc_walk_expr (gfc_expr * expr)
4437{
4438 gfc_ss *res;
4439
4440 res = gfc_walk_subexpr (gfc_ss_terminator, expr);
4441 return gfc_reverse_ss (res);
4442}
4443
This page took 0.820358 seconds and 5 git commands to generate.