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