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